Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: ipc/ipc_channel_win.cc

Issue 9547009: Factor out the shared parts of IPC channel reading. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ipc/ipc_channel_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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_win.h" 5 #include "ipc/ipc_channel_win.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 8
9 #include "base/auto_reset.h" 9 #include "base/auto_reset.h"
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 12 matching lines...) Expand all
23 context.handler = channel; 23 context.handler = channel;
24 } 24 }
25 25
26 Channel::ChannelImpl::State::~State() { 26 Channel::ChannelImpl::State::~State() {
27 COMPILE_ASSERT(!offsetof(Channel::ChannelImpl::State, context), 27 COMPILE_ASSERT(!offsetof(Channel::ChannelImpl::State, context),
28 starts_with_io_context); 28 starts_with_io_context);
29 } 29 }
30 30
31 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle &channel_handle, 31 Channel::ChannelImpl::ChannelImpl(const IPC::ChannelHandle &channel_handle,
32 Mode mode, Listener* listener) 32 Mode mode, Listener* listener)
33 : ALLOW_THIS_IN_INITIALIZER_LIST(input_state_(this)), 33 : ChannelReader(listener),
34 ALLOW_THIS_IN_INITIALIZER_LIST(input_state_(this)),
34 ALLOW_THIS_IN_INITIALIZER_LIST(output_state_(this)), 35 ALLOW_THIS_IN_INITIALIZER_LIST(output_state_(this)),
35 pipe_(INVALID_HANDLE_VALUE), 36 pipe_(INVALID_HANDLE_VALUE),
36 listener_(listener),
37 waiting_connect_(mode & MODE_SERVER_FLAG), 37 waiting_connect_(mode & MODE_SERVER_FLAG),
38 processing_incoming_(false), 38 processing_incoming_(false),
39 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { 39 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
40 CreatePipe(channel_handle, mode); 40 CreatePipe(channel_handle, mode);
41 } 41 }
42 42
43 Channel::ChannelImpl::~ChannelImpl() { 43 Channel::ChannelImpl::~ChannelImpl() {
44 Close(); 44 Close();
45 } 45 }
46 46
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 106
107 107
108 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData( 108 Channel::ChannelImpl::ReadState Channel::ChannelImpl::ReadData(
109 char* buffer, 109 char* buffer,
110 int buffer_len, 110 int buffer_len,
111 int* /* bytes_read */) { 111 int* /* bytes_read */) {
112 if (INVALID_HANDLE_VALUE == pipe_) 112 if (INVALID_HANDLE_VALUE == pipe_)
113 return READ_FAILED; 113 return READ_FAILED;
114 114
115 DWORD bytes_read = 0; 115 DWORD bytes_read = 0;
116 BOOL ok = ReadFile(pipe_, input_buf_, Channel::kReadBufferSize, 116 BOOL ok = ReadFile(pipe_, buffer, buffer_len,
117 &bytes_read, &input_state_.context.overlapped); 117 &bytes_read, &input_state_.context.overlapped);
118 if (!ok) { 118 if (!ok) {
119 DWORD err = GetLastError(); 119 DWORD err = GetLastError();
120 if (err == ERROR_IO_PENDING) { 120 if (err == ERROR_IO_PENDING) {
121 input_state_.is_pending = true; 121 input_state_.is_pending = true;
122 return READ_PENDING; 122 return READ_PENDING;
123 } 123 }
124 LOG(ERROR) << "pipe error: " << err; 124 LOG(ERROR) << "pipe error: " << err;
125 return READ_FAILED; 125 return READ_FAILED;
126 } 126 }
127 127
128 // We could return READ_SUCCEEDED here. But the way that this code is 128 // We could return READ_SUCCEEDED here. But the way that this code is
129 // structured we instead go back to the message loop. Our completion port 129 // structured we instead go back to the message loop. Our completion port
130 // will be signalled even in the "synchronously completed" state. 130 // will be signalled even in the "synchronously completed" state.
131 // 131 //
132 // This allows us to potentially process some outgoing messages and 132 // This allows us to potentially process some outgoing messages and
133 // interleave other work on this thread when we're getting hammered with 133 // interleave other work on this thread when we're getting hammered with
134 // input messages. Potentially, this could be tuned to be more efficient 134 // input messages. Potentially, this could be tuned to be more efficient
135 // with some testing. 135 // with some testing.
136 input_state_.is_pending = true; 136 input_state_.is_pending = true;
137 return READ_PENDING; 137 return READ_PENDING;
138 } 138 }
139 139
140 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) { 140 bool Channel::ChannelImpl::WillDispatchInputMessage(Message* msg) {
141 // We don't need to do anything here.
141 return true; 142 return true;
142 } 143 }
143 144
144 void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) { 145 void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) {
145 // The hello message contains one parameter containing the PID. 146 // The hello message contains one parameter containing the PID.
146 listener_->OnChannelConnected(MessageIterator(msg).NextInt()); 147 listener()->OnChannelConnected(MessageIterator(msg).NextInt());
147 } 148 }
148 149
149 bool Channel::ChannelImpl::DidEmptyInputBuffers() { 150 bool Channel::ChannelImpl::DidEmptyInputBuffers() {
151 // We don't need to do anything here.
150 return true; 152 return true;
151 } 153 }
152 154
153 bool Channel::ChannelImpl::DispatchInputData(const char* input_data,
154 int input_data_len) {
155 const char* p;
156 const char* end;
157
158 // Possibly combine with the overflow buffer to make a larger buffer.
159 if (input_overflow_buf_.empty()) {
160 p = input_data;
161 end = input_data + input_data_len;
162 } else {
163 if (input_overflow_buf_.size() >
164 kMaximumMessageSize - input_data_len) {
165 input_overflow_buf_.clear();
166 LOG(ERROR) << "IPC message is too big";
167 return false;
168 }
169 input_overflow_buf_.append(input_data, input_data_len);
170 p = input_overflow_buf_.data();
171 end = p + input_overflow_buf_.size();
172 }
173
174 // Dispatch all complete messages in the data buffer.
175 while (p < end) {
176 const char* message_tail = Message::FindNext(p, end);
177 if (message_tail) {
178 int len = static_cast<int>(message_tail - p);
179 Message m(p, len);
180 if (!WillDispatchInputMessage(&m))
181 return false;
182
183 if (IsHelloMessage(m))
184 HandleHelloMessage(m);
185 else
186 listener_->OnMessageReceived(m);
187 p = message_tail;
188 } else {
189 // Last message is partial.
190 break;
191 }
192 }
193
194 // Save any partial data in the overflow buffer.
195 input_overflow_buf_.assign(p, end - p);
196
197 if (input_overflow_buf_.empty() && !DidEmptyInputBuffers())
198 return false;
199 return true;
200 }
201
202 bool Channel::ChannelImpl::IsHelloMessage(const Message& m) const {
203 return m.routing_id() == MSG_ROUTING_NONE && m.type() == HELLO_MESSAGE_TYPE;
204 }
205
206 bool Channel::ChannelImpl::AsyncReadComplete(int bytes_read) {
207 return DispatchInputData(input_buf_, bytes_read);
208 }
209
210 // static 155 // static
211 const std::wstring Channel::ChannelImpl::PipeName( 156 const std::wstring Channel::ChannelImpl::PipeName(
212 const std::string& channel_id) { 157 const std::string& channel_id) {
213 std::string name("\\\\.\\pipe\\chrome."); 158 std::string name("\\\\.\\pipe\\chrome.");
214 return ASCIIToWide(name.append(channel_id)); 159 return ASCIIToWide(name.append(channel_id));
215 } 160 }
216 161
217 bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle, 162 bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle &channel_handle,
218 Mode mode) { 163 Mode mode) {
219 DCHECK_EQ(INVALID_HANDLE_VALUE, pipe_); 164 DCHECK_EQ(INVALID_HANDLE_VALUE, pipe_);
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 // The pipe is being closed. 298 // The pipe is being closed.
354 return false; 299 return false;
355 default: 300 default:
356 NOTREACHED(); 301 NOTREACHED();
357 return false; 302 return false;
358 } 303 }
359 304
360 return true; 305 return true;
361 } 306 }
362 307
363 bool Channel::ChannelImpl::ProcessIncomingMessages() {
364 while (true) {
365 int bytes_read = 0;
366 ReadState read_state = ReadData(input_buf_, Channel::kReadBufferSize,
367 &bytes_read);
368 if (read_state == READ_FAILED)
369 return false;
370 if (read_state == READ_PENDING)
371 return true;
372 DCHECK(bytes_read > 0);
373 if (!DispatchInputData(input_buf_, bytes_read))
374 return false;
375 }
376 }
377
378 bool Channel::ChannelImpl::ProcessOutgoingMessages( 308 bool Channel::ChannelImpl::ProcessOutgoingMessages(
379 MessageLoopForIO::IOContext* context, 309 MessageLoopForIO::IOContext* context,
380 DWORD bytes_written) { 310 DWORD bytes_written) {
381 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 311 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
382 // no connection? 312 // no connection?
383 DCHECK(thread_check_->CalledOnValidThread()); 313 DCHECK(thread_check_->CalledOnValidThread());
384 314
385 if (output_state_.is_pending) { 315 if (output_state_.is_pending) {
386 DCHECK(context); 316 DCHECK(context);
387 output_state_.is_pending = false; 317 output_state_.is_pending = false;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 // Request more data. 398 // Request more data.
469 if (ok) 399 if (ok)
470 ok = ProcessIncomingMessages(); 400 ok = ProcessIncomingMessages();
471 } else { 401 } else {
472 DCHECK(context == &output_state_.context); 402 DCHECK(context == &output_state_.context);
473 ok = ProcessOutgoingMessages(context, bytes_transfered); 403 ok = ProcessOutgoingMessages(context, bytes_transfered);
474 } 404 }
475 if (!ok && INVALID_HANDLE_VALUE != pipe_) { 405 if (!ok && INVALID_HANDLE_VALUE != pipe_) {
476 // We don't want to re-enter Close(). 406 // We don't want to re-enter Close().
477 Close(); 407 Close();
478 listener_->OnChannelError(); 408 listener()->OnChannelError();
479 } 409 }
480 } 410 }
481 411
482 //------------------------------------------------------------------------------ 412 //------------------------------------------------------------------------------
483 // Channel's methods simply call through to ChannelImpl. 413 // Channel's methods simply call through to ChannelImpl.
484 Channel::Channel(const IPC::ChannelHandle &channel_handle, Mode mode, 414 Channel::Channel(const IPC::ChannelHandle &channel_handle, Mode mode,
485 Listener* listener) 415 Listener* listener)
486 : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) { 416 : channel_impl_(new ChannelImpl(channel_handle, mode, listener)) {
487 } 417 }
488 418
(...skipping 16 matching lines...) Expand all
505 bool Channel::Send(Message* message) { 435 bool Channel::Send(Message* message) {
506 return channel_impl_->Send(message); 436 return channel_impl_->Send(message);
507 } 437 }
508 438
509 // static 439 // static
510 bool Channel::IsNamedServerInitialized(const std::string& channel_id) { 440 bool Channel::IsNamedServerInitialized(const std::string& channel_id) {
511 return ChannelImpl::IsNamedServerInitialized(channel_id); 441 return ChannelImpl::IsNamedServerInitialized(channel_id);
512 } 442 }
513 443
514 } // namespace IPC 444 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc_channel_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698