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 |