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 "ipc/ipc_listener.h" | 7 #include "ipc/ipc_listener.h" |
8 #include "ipc/ipc_logging.h" | 8 #include "ipc/ipc_logging.h" |
9 #include "ipc/ipc_message.h" | |
10 #include "ipc/ipc_message_attachment_set.h" | |
9 #include "ipc/ipc_message_macros.h" | 11 #include "ipc/ipc_message_macros.h" |
10 | 12 |
11 namespace IPC { | 13 namespace IPC { |
12 namespace internal { | 14 namespace internal { |
13 | 15 |
14 ChannelReader::ChannelReader(Listener* listener) : listener_(listener) { | 16 ChannelReader::ChannelReader(Listener* listener) : listener_(listener) { |
15 memset(input_buf_, 0, sizeof(input_buf_)); | 17 memset(input_buf_, 0, sizeof(input_buf_)); |
16 } | 18 } |
17 | 19 |
18 ChannelReader::~ChannelReader() { | 20 ChannelReader::~ChannelReader() { |
21 if (!blocked_ids_.empty()) | |
22 StopObservingAttachmentBroker(); | |
19 } | 23 } |
20 | 24 |
21 bool ChannelReader::ProcessIncomingMessages() { | 25 ChannelReader::DispatchState ChannelReader::ProcessIncomingMessages() { |
22 while (true) { | 26 while (true) { |
23 int bytes_read = 0; | 27 int bytes_read = 0; |
24 ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize, | 28 ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize, |
25 &bytes_read); | 29 &bytes_read); |
26 if (read_state == READ_FAILED) | 30 if (read_state == READ_FAILED) |
27 return false; | 31 return DISPATCH_ERROR; |
28 if (read_state == READ_PENDING) | 32 if (read_state == READ_PENDING) |
29 return true; | 33 return DISPATCH_FINISHED; |
30 | 34 |
31 DCHECK(bytes_read > 0); | 35 DCHECK(bytes_read > 0); |
32 if (!DispatchInputData(input_buf_, bytes_read)) | 36 if (!TranslateInputData(input_buf_, bytes_read)) |
33 return false; | 37 return DISPATCH_ERROR; |
38 | |
39 DispatchState state = DispatchMessages(); | |
40 if (state != DISPATCH_FINISHED) | |
41 return state; | |
34 } | 42 } |
35 } | 43 } |
36 | 44 |
37 bool ChannelReader::AsyncReadComplete(int bytes_read) { | 45 ChannelReader::DispatchState ChannelReader::AsyncReadComplete(int bytes_read) { |
38 return DispatchInputData(input_buf_, bytes_read); | 46 if (!TranslateInputData(input_buf_, bytes_read)) |
47 return DISPATCH_ERROR; | |
48 | |
49 return DispatchMessages(); | |
39 } | 50 } |
40 | 51 |
41 bool ChannelReader::IsInternalMessage(const Message& m) { | 52 bool ChannelReader::IsInternalMessage(const Message& m) { |
42 return m.routing_id() == MSG_ROUTING_NONE && | 53 return m.routing_id() == MSG_ROUTING_NONE && |
43 m.type() >= Channel::CLOSE_FD_MESSAGE_TYPE && | 54 m.type() >= Channel::CLOSE_FD_MESSAGE_TYPE && |
44 m.type() <= Channel::HELLO_MESSAGE_TYPE; | 55 m.type() <= Channel::HELLO_MESSAGE_TYPE; |
45 } | 56 } |
46 | 57 |
47 bool ChannelReader::IsHelloMessage(const Message& m) { | 58 bool ChannelReader::IsHelloMessage(const Message& m) { |
48 return m.routing_id() == MSG_ROUTING_NONE && | 59 return m.routing_id() == MSG_ROUTING_NONE && |
49 m.type() == Channel::HELLO_MESSAGE_TYPE; | 60 m.type() == Channel::HELLO_MESSAGE_TYPE; |
50 } | 61 } |
51 | 62 |
52 bool ChannelReader::DispatchInputData(const char* input_data, | 63 bool ChannelReader::TranslateInputData(const char* input_data, |
53 int input_data_len) { | 64 int input_data_len) { |
54 const char* p; | 65 const char* p; |
55 const char* end; | 66 const char* end; |
56 | 67 |
57 // Possibly combine with the overflow buffer to make a larger buffer. | 68 // Possibly combine with the overflow buffer to make a larger buffer. |
58 if (input_overflow_buf_.empty()) { | 69 if (input_overflow_buf_.empty()) { |
59 p = input_data; | 70 p = input_data; |
60 end = input_data + input_data_len; | 71 end = input_data + input_data_len; |
61 } else { | 72 } else { |
62 if (input_overflow_buf_.size() + input_data_len > | 73 if (input_overflow_buf_.size() + input_data_len > |
63 Channel::kMaximumMessageSize) { | 74 Channel::kMaximumMessageSize) { |
64 input_overflow_buf_.clear(); | 75 input_overflow_buf_.clear(); |
65 LOG(ERROR) << "IPC message is too big"; | 76 LOG(ERROR) << "IPC message is too big"; |
66 return false; | 77 return false; |
67 } | 78 } |
68 input_overflow_buf_.append(input_data, input_data_len); | 79 input_overflow_buf_.append(input_data, input_data_len); |
69 p = input_overflow_buf_.data(); | 80 p = input_overflow_buf_.data(); |
70 end = p + input_overflow_buf_.size(); | 81 end = p + input_overflow_buf_.size(); |
71 } | 82 } |
72 | 83 |
73 // Dispatch all complete messages in the data buffer. | 84 // Dispatch all complete messages in the data buffer. |
74 while (p < end) { | 85 while (p < end) { |
75 const char* message_tail = Message::FindNext(p, end); | 86 const char* message_tail = Message::FindNext(p, end); |
76 if (message_tail) { | 87 if (message_tail) { |
77 int len = static_cast<int>(message_tail - p); | 88 int len = static_cast<int>(message_tail - p); |
78 Message m(p, len); | 89 Message* m = new Message(p, len); |
79 if (!WillDispatchInputMessage(&m)) | 90 if (!GetNonBrokeredAttachments(m)) |
Tom Sepez
2015/07/13 18:28:47
Do we leak |m| here if we return early?
erikchen
2015/07/17 18:44:01
Yup. That's what I deserve for not using scoped_pt
| |
80 return false; | 91 return false; |
81 | 92 |
82 #ifdef IPC_MESSAGE_LOG_ENABLED | 93 queued_messages_.push_back(m); |
83 std::string name; | |
84 Logging::GetInstance()->GetMessageText(m.type(), &name, &m, NULL); | |
85 TRACE_EVENT1("ipc,toplevel", "ChannelReader::DispatchInputData", | |
86 "name", name); | |
87 #else | |
88 TRACE_EVENT2("ipc,toplevel", "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 if (m.dispatch_error()) | |
98 listener_->OnBadMessageReceived(m); | |
99 p = message_tail; | 94 p = message_tail; |
100 } else { | 95 } else { |
101 // Last message is partial. | 96 // Last message is partial. |
102 break; | 97 break; |
103 } | 98 } |
104 } | 99 } |
105 | 100 |
106 // Save any partial data in the overflow buffer. | 101 // Save any partial data in the overflow buffer. |
107 input_overflow_buf_.assign(p, end - p); | 102 input_overflow_buf_.assign(p, end - p); |
108 | 103 |
109 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) | 104 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers()) |
110 return false; | 105 return false; |
111 return true; | 106 return true; |
112 } | 107 } |
113 | 108 |
109 ChannelReader::DispatchState ChannelReader::DispatchMessages() { | |
110 while (!queued_messages_.empty()) { | |
111 if (!blocked_ids_.empty()) | |
112 return DISPATCH_WAITING_ON_BROKER; | |
113 | |
114 Message* m = queued_messages_.front(); | |
115 | |
116 AttachmentIdSet blocked_ids = GetBrokeredAttachments(m); | |
117 if (!blocked_ids.empty()) { | |
118 blocked_ids_.swap(blocked_ids); | |
119 StartObservingAttachmentBroker(); | |
120 return DISPATCH_WAITING_ON_BROKER; | |
121 } | |
122 | |
123 DispatchMessage(m); | |
124 queued_messages_.erase(queued_messages_.begin()); | |
125 } | |
126 return DISPATCH_FINISHED; | |
127 } | |
128 | |
129 void ChannelReader::DispatchMessage(Message* m) { | |
130 #ifdef IPC_MESSAGE_LOG_ENABLED | |
131 std::string name; | |
132 Logging::GetInstance()->GetMessageText(m->type(), &name, m, NULL); | |
133 TRACE_EVENT1("ipc,toplevel", "ChannelReader::DispatchInputData", "name", | |
134 name); | |
135 #else | |
136 TRACE_EVENT2("ipc,toplevel", "ChannelReader::DispatchInputData", "class", | |
137 IPC_MESSAGE_ID_CLASS(m->type()), "line", | |
138 IPC_MESSAGE_ID_LINE(m->type())); | |
139 #endif | |
140 m->TraceMessageEnd(); | |
141 if (IsInternalMessage(*m)) | |
142 HandleInternalMessage(*m); | |
143 else | |
144 listener_->OnMessageReceived(*m); | |
145 if (m->dispatch_error()) | |
146 listener_->OnBadMessageReceived(*m); | |
147 } | |
148 | |
149 ChannelReader::AttachmentIdSet ChannelReader::GetBrokeredAttachments( | |
150 Message* msg) { | |
151 std::set<BrokerableAttachment::AttachmentId> blocked_ids; | |
152 | |
153 MessageAttachmentSet* set = msg->attachment_set(); | |
154 for (const scoped_refptr<BrokerableAttachment>& attachment : | |
155 set->GetBrokerableAttachmentsForUpdating()) { | |
156 if (attachment->NeedsBrokering()) { | |
157 AttachmentBroker* broker = GetAttachmentBroker(); | |
158 scoped_refptr<BrokerableAttachment> brokered_attachment; | |
159 bool result = broker->GetAttachmentWithId(attachment->GetIdentifier(), | |
160 &brokered_attachment); | |
161 if (!result) { | |
162 blocked_ids.insert(attachment->GetIdentifier()); | |
163 continue; | |
164 } | |
165 | |
166 attachment->PopulateWithAttachment(brokered_attachment.get()); | |
167 } | |
168 } | |
169 | |
170 return blocked_ids; | |
171 } | |
172 | |
173 void ChannelReader::ReceivedBrokerableAttachmentWithId( | |
174 const BrokerableAttachment::AttachmentId& id) { | |
175 if (blocked_ids_.empty()) | |
176 return; | |
177 | |
178 for (AttachmentIdSet::iterator it = blocked_ids_.begin(); | |
Tom Sepez
2015/07/13 18:28:47
nit: find()
erikchen
2015/07/17 18:44:01
Done.
| |
179 it != blocked_ids_.end(); ++it) { | |
180 if (*it == id) { | |
181 blocked_ids_.erase(it); | |
182 break; | |
183 } | |
184 } | |
185 | |
186 if (blocked_ids_.empty()) { | |
187 StopObservingAttachmentBroker(); | |
188 DispatchMessages(); | |
189 } | |
190 } | |
191 | |
192 void ChannelReader::StartObservingAttachmentBroker() { | |
193 GetAttachmentBroker()->AddObserver(this); | |
194 } | |
195 | |
196 void ChannelReader::StopObservingAttachmentBroker() { | |
197 GetAttachmentBroker()->RemoveObserver(this); | |
198 } | |
114 | 199 |
115 } // namespace internal | 200 } // namespace internal |
116 } // namespace IPC | 201 } // namespace IPC |
OLD | NEW |