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

Side by Side Diff: ipc/ipc_channel_posix.cc

Issue 6334061: Clean up channel modes (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed up agl's comments Created 9 years, 10 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_posix.h ('k') | ipc/ipc_channel_proxy.cc » ('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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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_posix.h" 5 #include "ipc/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> 9 #include <stddef.h>
10 #include <sys/types.h> 10 #include <sys/types.h>
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 pipe_(-1), 311 pipe_(-1),
312 client_pipe_(-1), 312 client_pipe_(-1),
313 #if defined(IPC_USES_READWRITE) 313 #if defined(IPC_USES_READWRITE)
314 fd_pipe_(-1), 314 fd_pipe_(-1),
315 remote_fd_pipe_(-1), 315 remote_fd_pipe_(-1),
316 #endif // IPC_USES_READWRITE 316 #endif // IPC_USES_READWRITE
317 pipe_name_(channel_handle.name), 317 pipe_name_(channel_handle.name),
318 listener_(listener), 318 listener_(listener),
319 must_unlink_(false), 319 must_unlink_(false),
320 factory_(this) { 320 factory_(this) {
321 // Check to see if we want to implement using domain sockets. 321 if (!CreatePipe(channel_handle)) {
322 bool uses_domain_socket = false;
323 bool listening_socket = false;
324 if (mode_ == MODE_NAMED_SERVER) {
325 uses_domain_socket = true;
326 listening_socket = true;
327 mode_ = MODE_SERVER;
328 } else if (mode_ == MODE_NAMED_CLIENT) {
329 uses_domain_socket = true;
330 mode_ = MODE_CLIENT;
331 }
332 if (!CreatePipe(channel_handle, uses_domain_socket, listening_socket)) {
333 // The pipe may have been closed already. 322 // The pipe may have been closed already.
334 const char *modestr = (mode_ == MODE_SERVER 323 const char *modestr = (mode_ & MODE_SERVER_FLAG) ? "server" : "client";
335 || mode_ == MODE_NAMED_SERVER) ? "server" : "client";
336 // The pipe may have been closed already. 324 // The pipe may have been closed already.
337 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name 325 LOG(WARNING) << "Unable to create pipe named \"" << channel_handle.name
338 << "\" in " << modestr << " mode"; 326 << "\" in " << modestr << " mode";
339 } 327 }
340 } 328 }
341 329
342 Channel::ChannelImpl::~ChannelImpl() { 330 Channel::ChannelImpl::~ChannelImpl() {
343 Close(); 331 Close();
344 } 332 }
345 333
(...skipping 14 matching lines...) Expand all
360 PLOG(ERROR) << "close"; 348 PLOG(ERROR) << "close";
361 return false; 349 return false;
362 } 350 }
363 351
364 *fd1 = pipe_fds[0]; 352 *fd1 = pipe_fds[0];
365 *fd2 = pipe_fds[1]; 353 *fd2 = pipe_fds[1];
366 354
367 return true; 355 return true;
368 } 356 }
369 357
370 bool Channel::ChannelImpl::CreatePipe(const IPC::ChannelHandle& channel_handle, 358 bool Channel::ChannelImpl::CreatePipe(
371 bool uses_domain_sockets, 359 const IPC::ChannelHandle& channel_handle) {
372 bool listening_socket) {
373 DCHECK(server_listen_pipe_ == -1 && pipe_ == -1); 360 DCHECK(server_listen_pipe_ == -1 && pipe_ == -1);
374 361
375 // Four possible cases: 362 // Four possible cases:
376 // 1) It's a channel wrapping a pipe that is given to us. 363 // 1) It's a channel wrapping a pipe that is given to us.
377 // 2) It's for a named channel, so we create it. 364 // 2) It's for a named channel, so we create it.
378 // 3) It's for a client that we implement ourself. This is used 365 // 3) It's for a client that we implement ourself. This is used
379 // in unittesting. 366 // in unittesting.
380 // 4) It's the initial IPC channel: 367 // 4) It's the initial IPC channel:
381 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. 368 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set.
382 // 4b) Server side: create the pipe. 369 // 4b) Server side: create the pipe.
383 370
384 if (channel_handle.socket.fd != -1) { 371 if (channel_handle.socket.fd != -1) {
385 // Case 1 from comment above. 372 // Case 1 from comment above.
386 pipe_ = channel_handle.socket.fd; 373 pipe_ = channel_handle.socket.fd;
387 #if defined(IPC_USES_READWRITE) 374 #if defined(IPC_USES_READWRITE)
388 // Test the socket passed into us to make sure it is nonblocking. 375 // Test the socket passed into us to make sure it is nonblocking.
389 // We don't want to call read/write on a blocking socket. 376 // We don't want to call read/write on a blocking socket.
390 int value = fcntl(pipe_, F_GETFL); 377 int value = fcntl(pipe_, F_GETFL);
391 if (value == -1) { 378 if (value == -1) {
392 PLOG(ERROR) << "fcntl(F_GETFL) " << pipe_name_; 379 PLOG(ERROR) << "fcntl(F_GETFL) " << pipe_name_;
393 return false; 380 return false;
394 } 381 }
395 if (!(value & O_NONBLOCK)) { 382 if (!(value & O_NONBLOCK)) {
396 LOG(ERROR) << "Socket " << pipe_name_ << " must be O_NONBLOCK"; 383 LOG(ERROR) << "Socket " << pipe_name_ << " must be O_NONBLOCK";
397 return false; 384 return false;
398 } 385 }
399 #endif // IPC_USES_READWRITE 386 #endif // IPC_USES_READWRITE
400 } else if (uses_domain_sockets) { 387 } else if (mode_ & MODE_NAMED_FLAG) {
401 // Case 2 from comment above. 388 // Case 2 from comment above.
402 must_unlink_ = true; 389 must_unlink_ = true;
403 if (mode_ == MODE_SERVER) { 390 if (mode_ & MODE_SERVER_FLAG) {
404 if (!CreateServerUnixDomainSocket(pipe_name_, &pipe_)) { 391 if (!CreateServerUnixDomainSocket(pipe_name_, &pipe_)) {
405 return false; 392 return false;
406 } 393 }
407 } else if (mode_ == MODE_CLIENT) { 394 } else if (mode_ & MODE_CLIENT_FLAG) {
408 if (!CreateClientUnixDomainSocket(pipe_name_, &pipe_)) { 395 if (!CreateClientUnixDomainSocket(pipe_name_, &pipe_)) {
409 return false; 396 return false;
410 } 397 }
398 } else {
399 NOTREACHED();
400 return false;
411 } 401 }
412 } else { 402 } else {
413 pipe_ = PipeMap::GetInstance()->Lookup(pipe_name_); 403 pipe_ = PipeMap::GetInstance()->Lookup(pipe_name_);
414 if (mode_ == MODE_CLIENT) { 404 if (mode_ & MODE_CLIENT_FLAG) {
415 if (pipe_ != -1) { 405 if (pipe_ != -1) {
416 // Case 3 from comment above. 406 // Case 3 from comment above.
417 // We only allow one connection. 407 // We only allow one connection.
418 pipe_ = HANDLE_EINTR(dup(pipe_)); 408 pipe_ = HANDLE_EINTR(dup(pipe_));
419 PipeMap::GetInstance()->RemoveAndClose(pipe_name_); 409 PipeMap::GetInstance()->RemoveAndClose(pipe_name_);
420 } else { 410 } else {
421 // Case 4a from comment above. 411 // Case 4a from comment above.
422 // Guard against inappropriate reuse of the initial IPC channel. If 412 // Guard against inappropriate reuse of the initial IPC channel. If
423 // an IPC channel closes and someone attempts to reuse it by name, the 413 // an IPC channel closes and someone attempts to reuse it by name, the
424 // initial channel must not be recycled here. http://crbug.com/26754. 414 // initial channel must not be recycled here. http://crbug.com/26754.
425 static bool used_initial_channel = false; 415 static bool used_initial_channel = false;
426 if (used_initial_channel) { 416 if (used_initial_channel) {
427 LOG(FATAL) << "Denying attempt to reuse initial IPC channel for " 417 LOG(FATAL) << "Denying attempt to reuse initial IPC channel for "
428 << pipe_name_; 418 << pipe_name_;
429 return false; 419 return false;
430 } 420 }
431 used_initial_channel = true; 421 used_initial_channel = true;
432 422
433 pipe_ = base::GlobalDescriptors::GetInstance()->Get(kPrimaryIPCChannel); 423 pipe_ = base::GlobalDescriptors::GetInstance()->Get(kPrimaryIPCChannel);
434 } 424 }
435 } else if (mode_ == MODE_SERVER) { 425 } else if (mode_ & MODE_SERVER_FLAG) {
436 // Case 4b from comment above. 426 // Case 4b from comment above.
437 if (pipe_ != -1) { 427 if (pipe_ != -1) {
438 LOG(ERROR) << "Server already exists for " << pipe_name_; 428 LOG(ERROR) << "Server already exists for " << pipe_name_;
439 return false; 429 return false;
440 } 430 }
441 if (!SocketPair(&pipe_, &client_pipe_)) 431 if (!SocketPair(&pipe_, &client_pipe_))
442 return false; 432 return false;
443 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_); 433 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_);
444 } else { 434 } else {
445 LOG(FATAL) << "Unknown mode " << mode_; 435 NOTREACHED();
446 return false; 436 return false;
447 } 437 }
448 } 438 }
449 439
450 if (mode_ == MODE_SERVER) { 440 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) {
451 if (listening_socket) { 441 server_listen_pipe_ = pipe_;
452 server_listen_pipe_ = pipe_; 442 pipe_ = -1;
453 pipe_ = -1;
454 }
455 } 443 }
456 444
457 #if defined(IPC_USES_READWRITE) 445 #if defined(IPC_USES_READWRITE)
458 // Create a dedicated socketpair() for exchanging file descriptors. 446 // Create a dedicated socketpair() for exchanging file descriptors.
459 // See comments for IPC_USES_READWRITE for details. 447 // See comments for IPC_USES_READWRITE for details.
460 if (mode_ == MODE_CLIENT) { 448 if (mode_ & MODE_CLIENT_FLAG) {
461 if (!SocketPair(&fd_pipe_, &remote_fd_pipe_)) { 449 if (!SocketPair(&fd_pipe_, &remote_fd_pipe_)) {
462 return false; 450 return false;
463 } 451 }
464 } 452 }
465 #endif // IPC_USES_READWRITE 453 #endif // IPC_USES_READWRITE
466 454
467 return true; 455 return true;
468 } 456 }
469 457
470 bool Channel::ChannelImpl::Connect() { 458 bool Channel::ChannelImpl::Connect() {
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 DVLOG(2) << "received message on channel @" << this 710 DVLOG(2) << "received message on channel @" << this
723 << " with type " << m.type() << " on fd " << pipe_; 711 << " with type " << m.type() << " on fd " << pipe_;
724 if (IsHelloMessage(&m)) { 712 if (IsHelloMessage(&m)) {
725 // The Hello message contains only the process id. 713 // The Hello message contains only the process id.
726 void *iter = NULL; 714 void *iter = NULL;
727 int pid; 715 int pid;
728 if (!m.ReadInt(&iter, &pid)) { 716 if (!m.ReadInt(&iter, &pid)) {
729 NOTREACHED(); 717 NOTREACHED();
730 } 718 }
731 #if defined(IPC_USES_READWRITE) 719 #if defined(IPC_USES_READWRITE)
732 if (mode_ == MODE_SERVER) { 720 if (mode_ & MODE_SERVER_FLAG) {
733 // With IPC_USES_READWRITE, the Hello message from the client to the 721 // With IPC_USES_READWRITE, the Hello message from the client to the
734 // server also contains the fd_pipe_, which will be used for all 722 // server also contains the fd_pipe_, which will be used for all
735 // subsequent file descriptor passing. 723 // subsequent file descriptor passing.
736 DCHECK_EQ(m.file_descriptor_set()->size(), 1U); 724 DCHECK_EQ(m.file_descriptor_set()->size(), 1U);
737 base::FileDescriptor descriptor; 725 base::FileDescriptor descriptor;
738 if (!m.ReadFileDescriptor(&iter, &descriptor)) { 726 if (!m.ReadFileDescriptor(&iter, &descriptor)) {
739 NOTREACHED(); 727 NOTREACHED();
740 } 728 }
741 fd_pipe_ = descriptor.fd; 729 fd_pipe_ = descriptor.fd;
742 CHECK(descriptor.auto_close); 730 CHECK(descriptor.auto_close);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 if (bytes_written > 0) { 833 if (bytes_written > 0) {
846 msg->file_descriptor_set()->CommitAll(); 834 msg->file_descriptor_set()->CommitAll();
847 } 835 }
848 } 836 }
849 #endif // IPC_USES_READWRITE 837 #endif // IPC_USES_READWRITE
850 } 838 }
851 839
852 if (bytes_written == 1) { 840 if (bytes_written == 1) {
853 fd_written = pipe_; 841 fd_written = pipe_;
854 #if defined(IPC_USES_READWRITE) 842 #if defined(IPC_USES_READWRITE)
855 if (mode_ != MODE_SERVER && IsHelloMessage(msg)) { 843 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(msg)) {
856 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); 844 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
857 } 845 }
858 if (!msgh.msg_controllen) { 846 if (!msgh.msg_controllen) {
859 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); 847 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write));
860 } else 848 } else
861 #endif // IPC_USES_READWRITE 849 #endif // IPC_USES_READWRITE
862 { 850 {
863 bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT)); 851 bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT));
864 } 852 }
865 } 853 }
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1000 return; 988 return;
1001 } 989 }
1002 pipe_ = new_pipe; 990 pipe_ = new_pipe;
1003 991
1004 if (!AcceptConnection()) { 992 if (!AcceptConnection()) {
1005 NOTREACHED() << "AcceptConnection should not fail on server"; 993 NOTREACHED() << "AcceptConnection should not fail on server";
1006 } 994 }
1007 send_server_hello_msg = true; 995 send_server_hello_msg = true;
1008 waiting_connect_ = false; 996 waiting_connect_ = false;
1009 } else if (fd == pipe_) { 997 } else if (fd == pipe_) {
1010 if (waiting_connect_ && mode_ == MODE_SERVER) { 998 if (waiting_connect_ && (mode_ & MODE_SERVER_FLAG)) {
1011 send_server_hello_msg = true; 999 send_server_hello_msg = true;
1012 waiting_connect_ = false; 1000 waiting_connect_ = false;
1013 } 1001 }
1014 if (!ProcessIncomingMessages()) { 1002 if (!ProcessIncomingMessages()) {
1015 ClosePipeOnError(); 1003 ClosePipeOnError();
1016 } 1004 }
1017 } else { 1005 } else {
1018 NOTREACHED() << "Unknown pipe " << fd; 1006 NOTREACHED() << "Unknown pipe " << fd;
1019 } 1007 }
1020 1008
(...skipping 16 matching lines...) Expand all
1037 } 1025 }
1038 1026
1039 bool Channel::ChannelImpl::AcceptConnection() { 1027 bool Channel::ChannelImpl::AcceptConnection() {
1040 MessageLoopForIO::current()->WatchFileDescriptor(pipe_, 1028 MessageLoopForIO::current()->WatchFileDescriptor(pipe_,
1041 true, 1029 true,
1042 MessageLoopForIO::WATCH_READ, 1030 MessageLoopForIO::WATCH_READ,
1043 &read_watcher_, 1031 &read_watcher_,
1044 this); 1032 this);
1045 QueueHelloMessage(); 1033 QueueHelloMessage();
1046 1034
1047 if (mode_ == MODE_CLIENT) { 1035 if (mode_ & MODE_CLIENT_FLAG) {
1048 // If we are a client we want to send a hello message out immediately. 1036 // If we are a client we want to send a hello message out immediately.
1049 // In server mode we will send a hello message when we receive one from a 1037 // In server mode we will send a hello message when we receive one from a
1050 // client. 1038 // client.
1051 waiting_connect_ = false; 1039 waiting_connect_ = false;
1052 return ProcessOutgoingMessages(); 1040 return ProcessOutgoingMessages();
1053 } else { 1041 } else if (mode_ & MODE_SERVER_FLAG) {
1054 waiting_connect_ = true; 1042 waiting_connect_ = true;
1055 return true; 1043 return true;
1044 } else {
1045 NOTREACHED();
1046 return false;
1056 } 1047 }
1057 } 1048 }
1058 1049
1059 void Channel::ChannelImpl::ClosePipeOnError() { 1050 void Channel::ChannelImpl::ClosePipeOnError() {
1060 if (HasAcceptedConnection()) { 1051 if (HasAcceptedConnection()) {
1061 ResetToAcceptingConnectionState(); 1052 ResetToAcceptingConnectionState();
1062 listener_->OnChannelError(); 1053 listener_->OnChannelError();
1063 } else { 1054 } else {
1064 Close(); 1055 Close();
1065 if (AcceptsConnections()) { 1056 if (AcceptsConnections()) {
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1157 1148
1158 bool Channel::HasAcceptedConnection() const { 1149 bool Channel::HasAcceptedConnection() const {
1159 return channel_impl_->HasAcceptedConnection(); 1150 return channel_impl_->HasAcceptedConnection();
1160 } 1151 }
1161 1152
1162 void Channel::ResetToAcceptingConnectionState() { 1153 void Channel::ResetToAcceptingConnectionState() {
1163 channel_impl_->ResetToAcceptingConnectionState(); 1154 channel_impl_->ResetToAcceptingConnectionState();
1164 } 1155 }
1165 1156
1166 } // namespace IPC 1157 } // namespace IPC
OLDNEW
« no previous file with comments | « ipc/ipc_channel_posix.h ('k') | ipc/ipc_channel_proxy.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698