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

Side by Side Diff: chrome/common/ipc_channel_posix.cc

Issue 14068: Reverting 6911. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years 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 | « chrome/common/ipc_channel_posix.h ('k') | net/base/listen_socket.h » ('j') | 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) 2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2008 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 "chrome/common/ipc_channel_posix.h" 5 #include "chrome/common/ipc_channel_posix.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <stddef.h>
10 #include <sys/types.h> 9 #include <sys/types.h>
11 #include <sys/socket.h> 10 #include <sys/socket.h>
12 #include <sys/stat.h> 11 #include <sys/stat.h>
13 #if defined(OS_LINUX) 12 #include <stddef.h>
14 #include <linux/un.h>
15 #elif defined(OS_MACOSX)
16 #include <sys/un.h>
17 #endif
18
19 13
20 #include "base/logging.h" 14 #include "base/logging.h"
21 #include "base/process_util.h" 15 #include "base/process_util.h"
22 #include "base/scoped_ptr.h" 16 #include "base/scoped_ptr.h"
23 #include "base/string_util.h" 17 #include "base/string_util.h"
24 #include "chrome/common/chrome_counters.h" 18 #include "chrome/common/chrome_counters.h"
25 #include "chrome/common/ipc_message_utils.h" 19 #include "chrome/common/ipc_message_utils.h"
26 20
21 #if defined(OS_LINUX)
22 #include <linux/un.h>
23 #elif defined(OS_MACOSX)
24 #include <sys/un.h>
25 #endif
26
27 namespace IPC { 27 namespace IPC {
28 28
29 //------------------------------------------------------------------------------ 29 //------------------------------------------------------------------------------
30 // TODO(playmobil): Only use FIFOs for debugging, for real work, use a 30 // TODO(playmobil): Only use FIFOs for debugging, for real work, use a
31 // socketpair. 31 // socketpair.
32 namespace { 32 namespace {
33 33
34 // The -1 is to take the NULL terminator into account. 34 // The -1 is to take the NULL terminator into account.
35 #if defined(OS_LINUX) 35 #if defined(OS_LINUX)
36 const size_t kMaxPipeNameLength = UNIX_PATH_MAX - 1; 36 const size_t kMaxPipeNameLength = UNIX_PATH_MAX - 1;
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 *client_socket = fd; 143 *client_socket = fd;
144 return true; 144 return true;
145 } 145 }
146 146
147 } // namespace 147 } // namespace
148 //------------------------------------------------------------------------------ 148 //------------------------------------------------------------------------------
149 149
150 Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode, 150 Channel::ChannelImpl::ChannelImpl(const std::wstring& channel_id, Mode mode,
151 Listener* listener) 151 Listener* listener)
152 : mode_(mode), 152 : mode_(mode),
153 is_blocked_on_write_(false), 153 server_listen_connection_event_(new EventHolder()),
154 read_event_(new EventHolder()),
155 write_event_(new EventHolder()),
154 message_send_bytes_written_(0), 156 message_send_bytes_written_(0),
155 server_listen_pipe_(-1), 157 server_listen_pipe_(-1),
156 pipe_(-1), 158 pipe_(-1),
157 listener_(listener), 159 listener_(listener),
158 waiting_connect_(true), 160 waiting_connect_(true),
159 processing_incoming_(false), 161 processing_incoming_(false),
160 factory_(this) { 162 factory_(this) {
161 if (!CreatePipe(channel_id, mode)) { 163 if (!CreatePipe(channel_id, mode)) {
162 // The pipe may have been closed already. 164 // The pipe may have been closed already.
163 LOG(WARNING) << "Unable to create pipe named \"" << channel_id << 165 LOG(WARNING) << "Unable to create pipe named \"" << channel_id <<
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 207
206 output_queue_.push(msg.release()); 208 output_queue_.push(msg.release());
207 return true; 209 return true;
208 } 210 }
209 211
210 bool Channel::ChannelImpl::Connect() { 212 bool Channel::ChannelImpl::Connect() {
211 if (mode_ == MODE_SERVER) { 213 if (mode_ == MODE_SERVER) {
212 if (server_listen_pipe_ == -1) { 214 if (server_listen_pipe_ == -1) {
213 return false; 215 return false;
214 } 216 }
215 MessageLoopForIO::current()->WatchFileDescriptor( 217 event *ev = &(server_listen_connection_event_->event);
216 server_listen_pipe_, 218 MessageLoopForIO::current()->WatchFileHandle(server_listen_pipe_,
217 true, 219 EV_READ | EV_PERSIST,
218 MessageLoopForIO::WATCH_READ, 220 ev,
219 &server_listen_connection_watcher_, 221 this);
220 this); 222 server_listen_connection_event_->is_active = true;
221 } else { 223 } else {
222 if (pipe_ == -1) { 224 if (pipe_ == -1) {
223 return false; 225 return false;
224 } 226 }
225 MessageLoopForIO::current()->WatchFileDescriptor( 227 MessageLoopForIO::current()->WatchFileHandle(pipe_,
226 pipe_, 228 EV_READ | EV_PERSIST,
227 true, 229 &(read_event_->event),
228 MessageLoopForIO::WATCH_READ, 230 this);
229 &read_watcher_, 231 read_event_->is_active = true;
230 this);
231 waiting_connect_ = false; 232 waiting_connect_ = false;
232 } 233 }
233 234
234 if (!waiting_connect_) 235 if (!waiting_connect_)
235 return ProcessOutgoingMessages(); 236 return ProcessOutgoingMessages();
236 return true; 237 return true;
237 } 238 }
238 239
239 bool Channel::ChannelImpl::ProcessIncomingMessages() { 240 bool Channel::ChannelImpl::ProcessIncomingMessages() {
240 ssize_t bytes_read = 0; 241 ssize_t bytes_read = 0;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
309 310
310 bytes_read = 0; // Get more data. 311 bytes_read = 0; // Get more data.
311 } 312 }
312 313
313 return true; 314 return true;
314 } 315 }
315 316
316 bool Channel::ChannelImpl::ProcessOutgoingMessages() { 317 bool Channel::ChannelImpl::ProcessOutgoingMessages() {
317 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 318 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
318 // no connection? 319 // no connection?
319 is_blocked_on_write_ = false;
320 320
321 if (output_queue_.empty()) 321 if (output_queue_.empty())
322 return true; 322 return true;
323 323
324 if (pipe_ == -1) 324 if (pipe_ == -1)
325 return false; 325 return false;
326 326
327 // If libevent was monitoring the socket for us (we blocked when trying to
328 // write a message last time), then delete the underlying libevent structure.
329 if (write_event_->is_active) {
330 // TODO(playmobil): This calls event_del(), but we can probably
331 // do with just calling event_add here.
332 MessageLoopForIO::current()->UnwatchFileHandle(&(write_event_->event));
333 write_event_->is_active = false;
334 }
335
327 // Write out all the messages we can till the write blocks or there are no 336 // Write out all the messages we can till the write blocks or there are no
328 // more outgoing messages. 337 // more outgoing messages.
329 while (!output_queue_.empty()) { 338 while (!output_queue_.empty()) {
330 Message* msg = output_queue_.front(); 339 Message* msg = output_queue_.front();
331 340
332 size_t amt_to_write = msg->size() - message_send_bytes_written_; 341 size_t amt_to_write = msg->size() - message_send_bytes_written_;
333 const char *out_bytes = reinterpret_cast<const char*>(msg->data()) + 342 const char *out_bytes = reinterpret_cast<const char*>(msg->data()) +
334 message_send_bytes_written_; 343 message_send_bytes_written_;
335 ssize_t bytes_written = -1; 344 ssize_t bytes_written = -1;
336 do { 345 do {
337 bytes_written = write(pipe_, out_bytes, amt_to_write); 346 bytes_written = write(pipe_, out_bytes, amt_to_write);
338 } while (bytes_written == -1 && errno == EINTR); 347 } while (bytes_written == -1 && errno == EINTR);
339 348
340 if (bytes_written < 0) { 349 if (bytes_written < 0) {
341 LOG(ERROR) << "pipe error: " << strerror(errno); 350 LOG(ERROR) << "pipe error: " << strerror(errno);
342 return false; 351 return false;
343 } 352 }
344 353
345 if (static_cast<size_t>(bytes_written) != amt_to_write) { 354 if (static_cast<size_t>(bytes_written) != amt_to_write) {
346 message_send_bytes_written_ += bytes_written; 355 message_send_bytes_written_ += bytes_written;
347 356
348 // Tell libevent to call us back once things are unblocked. 357 // Tell libevent to call us back once things are unblocked.
349 is_blocked_on_write_ = true; 358 MessageLoopForIO::current()->WatchFileHandle(server_listen_pipe_,
350 MessageLoopForIO::current()->WatchFileDescriptor( 359 EV_WRITE,
351 pipe_, 360 &(write_event_->event),
352 false, // One shot 361 this);
353 MessageLoopForIO::WATCH_WRITE, 362 write_event_->is_active = true;
354 &write_watcher_, 363
355 this);
356 } else { 364 } else {
357 message_send_bytes_written_ = 0; 365 message_send_bytes_written_ = 0;
358 366
359 // Message sent OK! 367 // Message sent OK!
360 #ifdef IPC_MESSAGE_DEBUG_EXTRA 368 #ifdef IPC_MESSAGE_DEBUG_EXTRA
361 DLOG(INFO) << "sent message @" << msg << " on channel @" << this << 369 DLOG(INFO) << "sent message @" << msg << " on channel @" << this <<
362 " with type " << msg->type(); 370 " with type " << msg->type();
363 #endif 371 #endif
364 output_queue_.pop(); 372 output_queue_.pop();
365 delete msg; 373 delete msg;
(...skipping 10 matching lines...) Expand all
376 << " (" << output_queue_.size() << " in queue)"; 384 << " (" << output_queue_.size() << " in queue)";
377 #endif 385 #endif
378 386
379 // TODO(playmobil): implement 387 // TODO(playmobil): implement
380 // #ifdef IPC_MESSAGE_LOG_ENABLED 388 // #ifdef IPC_MESSAGE_LOG_ENABLED
381 // Logging::current()->OnSendMessage(message, L""); 389 // Logging::current()->OnSendMessage(message, L"");
382 // #endif 390 // #endif
383 391
384 output_queue_.push(message); 392 output_queue_.push(message);
385 if (!waiting_connect_) { 393 if (!waiting_connect_) {
386 if (!is_blocked_on_write_) { 394 if (!write_event_->is_active) {
387 if (!ProcessOutgoingMessages()) 395 if (!ProcessOutgoingMessages())
388 return false; 396 return false;
389 } 397 }
390 } 398 }
391 399
392 return true; 400 return true;
393 } 401 }
394 402
395 // Called by libevent when we can read from th pipe without blocking. 403 // Called by libevent when we can read from th pipe without blocking.
396 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { 404 void Channel::ChannelImpl::OnFileReadReady(int fd) {
397 bool send_server_hello_msg = false; 405 bool send_server_hello_msg = false;
398 if (waiting_connect_ && mode_ == MODE_SERVER) { 406 if (waiting_connect_ && mode_ == MODE_SERVER) {
399 if (!ServerAcceptFifoConnection(server_listen_pipe_, &pipe_)) { 407 if (!ServerAcceptFifoConnection(server_listen_pipe_, &pipe_)) {
400 Close(); 408 Close();
401 } 409 }
402 410
403 // No need to watch the listening socket any longer since only one client 411 // No need to watch the listening socket any longer since only one client
404 // can connect. So unregister with libevent. 412 // can connect. So unregister with libevent.
405 server_listen_connection_watcher_.StopWatchingFileDescriptor(); 413 event *ev = &(server_listen_connection_event_->event);
414 MessageLoopForIO::current()->UnwatchFileHandle(ev);
415 server_listen_connection_event_->is_active = false;
406 416
407 // Start watching our end of the socket. 417 // Start watching our end of the socket.
408 MessageLoopForIO::current()->WatchFileDescriptor( 418 MessageLoopForIO::current()->WatchFileHandle(pipe_,
409 pipe_, 419 EV_READ | EV_PERSIST,
410 true, 420 &(read_event_->event),
411 MessageLoopForIO::WATCH_READ, 421 this);
412 &read_watcher_, 422 read_event_->is_active = true;
413 this);
414
415 waiting_connect_ = false; 423 waiting_connect_ = false;
416 send_server_hello_msg = true; 424 send_server_hello_msg = true;
417 } 425 }
418 426
419 if (!waiting_connect_ && fd == pipe_) { 427 if (!waiting_connect_ && fd == pipe_) {
420 if (!ProcessIncomingMessages()) { 428 if (!ProcessIncomingMessages()) {
421 Close(); 429 Close();
422 listener_->OnChannelError(); 430 listener_->OnChannelError();
423 } 431 }
424 } 432 }
425 433
426 // If we're a server and handshaking, then we want to make sure that we 434 // If we're a server and handshaking, then we want to make sure that we
427 // only send our handshake message after we've processed the client's. 435 // only send our handshake message after we've processed the client's.
428 // This gives us a chance to kill the client if the incoming handshake 436 // This gives us a chance to kill the client if the incoming handshake
429 // is invalid. 437 // is invalid.
430 if (send_server_hello_msg) { 438 if (send_server_hello_msg) {
431 // This should be our first write so there' sno chance we can block here...
432 DCHECK(is_blocked_on_write_ == false);
433 ProcessOutgoingMessages(); 439 ProcessOutgoingMessages();
434 } 440 }
435 } 441 }
436 442
437 // Called by libevent when we can write to the pipe without blocking. 443 // Called by libevent when we can write to the pipe without blocking.
438 void Channel::ChannelImpl::OnFileCanWriteWithoutBlocking(int fd) { 444 void Channel::ChannelImpl::OnFileWriteReady(int fd) {
439 if (!ProcessOutgoingMessages()) { 445 if (!ProcessOutgoingMessages()) {
440 Close(); 446 Close();
441 listener_->OnChannelError(); 447 listener_->OnChannelError();
442 } 448 }
443 } 449 }
444 450
445 void Channel::ChannelImpl::Close() { 451 void Channel::ChannelImpl::Close() {
446 // Close can be called multiple time, so we need to make sure we're 452 // Close can be called multiple time, so we need to make sure we're
447 // idempotent. 453 // idempotent.
448 454
449 // Unregister libevent for the listening socket and close it. 455 // Unregister libevent for the listening socket and close it.
450 server_listen_connection_watcher_.StopWatchingFileDescriptor(); 456 if (server_listen_connection_event_ &&
457 server_listen_connection_event_->is_active) {
458 MessageLoopForIO::current()->UnwatchFileHandle(
459 &(server_listen_connection_event_->event));
460 }
451 461
452 if (server_listen_pipe_ != -1) { 462 if (server_listen_pipe_ != -1) {
453 close(server_listen_pipe_); 463 close(server_listen_pipe_);
454 server_listen_pipe_ = -1; 464 server_listen_pipe_ = -1;
455 } 465 }
456 466
457 // Unregister libevent for the FIFO and close it. 467 // Unregister libevent for the FIFO and close it.
458 read_watcher_.StopWatchingFileDescriptor(); 468 if (read_event_ && read_event_->is_active) {
459 write_watcher_.StopWatchingFileDescriptor(); 469 MessageLoopForIO::current()->UnwatchFileHandle(&(read_event_->event));
470 }
471 if (write_event_ && write_event_->is_active) {
472 MessageLoopForIO::current()->UnwatchFileHandle(&(write_event_->event));
473 }
460 if (pipe_ != -1) { 474 if (pipe_ != -1) {
461 close(pipe_); 475 close(pipe_);
462 pipe_ = -1; 476 pipe_ = -1;
463 } 477 }
464 478
479 delete server_listen_connection_event_;
480 server_listen_connection_event_ = NULL;
481 delete read_event_;
482 read_event_ = NULL;
483 delete write_event_;
484 write_event_ = NULL;
485
465 // Unlink the FIFO 486 // Unlink the FIFO
466 unlink(pipe_name_.c_str()); 487 unlink(pipe_name_.c_str());
467 488
468 while (!output_queue_.empty()) { 489 while (!output_queue_.empty()) {
469 Message* m = output_queue_.front(); 490 Message* m = output_queue_.front();
470 output_queue_.pop(); 491 output_queue_.pop();
471 delete m; 492 delete m;
472 } 493 }
473 } 494 }
474 495
(...skipping 18 matching lines...) Expand all
493 514
494 void Channel::set_listener(Listener* listener) { 515 void Channel::set_listener(Listener* listener) {
495 channel_impl_->set_listener(listener); 516 channel_impl_->set_listener(listener);
496 } 517 }
497 518
498 bool Channel::Send(Message* message) { 519 bool Channel::Send(Message* message) {
499 return channel_impl_->Send(message); 520 return channel_impl_->Send(message);
500 } 521 }
501 522
502 } // namespace IPC 523 } // namespace IPC
OLDNEW
« no previous file with comments | « chrome/common/ipc_channel_posix.h ('k') | net/base/listen_socket.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698