| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |