| OLD | NEW |
| 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_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/socket.h> | 10 #include <sys/socket.h> |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 // 3) It's for a client that we implement ourself. This is used | 240 // 3) It's for a client that we implement ourself. This is used |
| 241 // in single-process unittesting. | 241 // in single-process unittesting. |
| 242 // 4) It's the initial IPC channel: | 242 // 4) It's the initial IPC channel: |
| 243 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. | 243 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. |
| 244 // 4b) Server side: create the pipe. | 244 // 4b) Server side: create the pipe. |
| 245 | 245 |
| 246 base::ScopedFD local_pipe; | 246 base::ScopedFD local_pipe; |
| 247 if (channel_handle.socket.fd != -1) { | 247 if (channel_handle.socket.fd != -1) { |
| 248 // Case 1 from comment above. | 248 // Case 1 from comment above. |
| 249 local_pipe.reset(channel_handle.socket.fd); | 249 local_pipe.reset(channel_handle.socket.fd); |
| 250 #if defined(IPC_USES_READWRITE) | |
| 251 // Test the socket passed into us to make sure it is nonblocking. | |
| 252 // We don't want to call read/write on a blocking socket. | |
| 253 int value = fcntl(local_pipe.get(), F_GETFL); | |
| 254 if (value == -1) { | |
| 255 PLOG(ERROR) << "fcntl(F_GETFL) " << pipe_name_; | |
| 256 return false; | |
| 257 } | |
| 258 if (!(value & O_NONBLOCK)) { | |
| 259 LOG(ERROR) << "Socket " << pipe_name_ << " must be O_NONBLOCK"; | |
| 260 return false; | |
| 261 } | |
| 262 #endif // IPC_USES_READWRITE | |
| 263 } else if (mode_ & MODE_NAMED_FLAG) { | 250 } else if (mode_ & MODE_NAMED_FLAG) { |
| 264 #if defined(OS_NACL_NONSFI) | 251 #if defined(OS_NACL_NONSFI) |
| 265 LOG(FATAL) | 252 LOG(FATAL) |
| 266 << "IPC channels in nacl_helper_nonsfi should not be in NAMED mode."; | 253 << "IPC channels in nacl_helper_nonsfi should not be in NAMED mode."; |
| 267 #else | 254 #else |
| 268 // Case 2 from comment above. | 255 // Case 2 from comment above. |
| 269 int local_pipe_fd = -1; | 256 int local_pipe_fd = -1; |
| 270 | 257 |
| 271 if (mode_ & MODE_SERVER_FLAG) { | 258 if (mode_ & MODE_SERVER_FLAG) { |
| 272 if (!CreateServerUnixDomainSocket(base::FilePath(pipe_name_), | 259 if (!CreateServerUnixDomainSocket(base::FilePath(pipe_name_), |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 return false; | 313 return false; |
| 327 local_pipe.reset(local_pipe_fd); | 314 local_pipe.reset(local_pipe_fd); |
| 328 client_pipe_.reset(client_pipe_fd); | 315 client_pipe_.reset(client_pipe_fd); |
| 329 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_fd); | 316 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_fd); |
| 330 } else { | 317 } else { |
| 331 LOG(ERROR) << "Bad mode: " << mode_; | 318 LOG(ERROR) << "Bad mode: " << mode_; |
| 332 return false; | 319 return false; |
| 333 } | 320 } |
| 334 } | 321 } |
| 335 | 322 |
| 336 #if defined(IPC_USES_READWRITE) | |
| 337 // Create a dedicated socketpair() for exchanging file descriptors. | |
| 338 // See comments for IPC_USES_READWRITE for details. | |
| 339 if (mode_ & MODE_CLIENT_FLAG) { | |
| 340 int fd_pipe_fd = 1, remote_fd_pipe_fd = -1; | |
| 341 if (!SocketPair(&fd_pipe_fd, &remote_fd_pipe_fd)) { | |
| 342 return false; | |
| 343 } | |
| 344 | |
| 345 fd_pipe_.reset(fd_pipe_fd); | |
| 346 remote_fd_pipe_.reset(remote_fd_pipe_fd); | |
| 347 } | |
| 348 #endif // IPC_USES_READWRITE | |
| 349 | |
| 350 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { | 323 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { |
| 351 #if defined(OS_NACL_NONSFI) | 324 #if defined(OS_NACL_NONSFI) |
| 352 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi " | 325 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi " |
| 353 << "should not be in NAMED or SERVER mode."; | 326 << "should not be in NAMED or SERVER mode."; |
| 354 #else | 327 #else |
| 355 server_listen_pipe_.reset(local_pipe.release()); | 328 server_listen_pipe_.reset(local_pipe.release()); |
| 356 #endif | 329 #endif |
| 357 } else { | 330 } else { |
| 358 pipe_.reset(local_pipe.release()); | 331 pipe_.reset(local_pipe.release()); |
| 359 } | 332 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 cmsg->cmsg_level = SOL_SOCKET; | 432 cmsg->cmsg_level = SOL_SOCKET; |
| 460 cmsg->cmsg_type = SCM_RIGHTS; | 433 cmsg->cmsg_type = SCM_RIGHTS; |
| 461 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); | 434 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); |
| 462 msg->attachment_set()->PeekDescriptors( | 435 msg->attachment_set()->PeekDescriptors( |
| 463 reinterpret_cast<int*>(CMSG_DATA(cmsg))); | 436 reinterpret_cast<int*>(CMSG_DATA(cmsg))); |
| 464 msgh.msg_controllen = cmsg->cmsg_len; | 437 msgh.msg_controllen = cmsg->cmsg_len; |
| 465 | 438 |
| 466 // DCHECK_LE above already checks that | 439 // DCHECK_LE above already checks that |
| 467 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow. | 440 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow. |
| 468 msg->header()->num_fds = static_cast<uint16>(num_fds); | 441 msg->header()->num_fds = static_cast<uint16>(num_fds); |
| 469 | |
| 470 #if defined(IPC_USES_READWRITE) | |
| 471 if (!IsHelloMessage(*msg)) { | |
| 472 // Only the Hello message sends the file descriptor with the message. | |
| 473 // Subsequently, we can send file descriptors on the dedicated | |
| 474 // fd_pipe_ which makes Seccomp sandbox operation more efficient. | |
| 475 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; | |
| 476 msgh.msg_iov = &fd_pipe_iov; | |
| 477 fd_written = fd_pipe_.get(); | |
| 478 bytes_written = | |
| 479 HANDLE_EINTR(sendmsg(fd_pipe_.get(), &msgh, MSG_DONTWAIT)); | |
| 480 msgh.msg_iov = &iov; | |
| 481 msgh.msg_controllen = 0; | |
| 482 if (bytes_written > 0) { | |
| 483 CloseFileDescriptors(msg); | |
| 484 } | |
| 485 } | |
| 486 #endif // IPC_USES_READWRITE | |
| 487 } | 442 } |
| 488 | 443 |
| 489 if (bytes_written == 1) { | 444 if (bytes_written == 1) { |
| 490 fd_written = pipe_.get(); | 445 fd_written = pipe_.get(); |
| 491 #if defined(IPC_USES_READWRITE) | 446 bytes_written = HANDLE_EINTR(sendmsg(pipe_.get(), &msgh, MSG_DONTWAIT)); |
| 492 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(*msg)) { | |
| 493 DCHECK_EQ(msg->attachment_set()->size(), 1U); | |
| 494 } | |
| 495 if (!msgh.msg_controllen) { | |
| 496 bytes_written = | |
| 497 HANDLE_EINTR(write(pipe_.get(), out_bytes, amt_to_write)); | |
| 498 } else | |
| 499 #endif // IPC_USES_READWRITE | |
| 500 { | |
| 501 bytes_written = HANDLE_EINTR(sendmsg(pipe_.get(), &msgh, MSG_DONTWAIT)); | |
| 502 } | |
| 503 } | 447 } |
| 504 if (bytes_written > 0) | 448 if (bytes_written > 0) |
| 505 CloseFileDescriptors(msg); | 449 CloseFileDescriptors(msg); |
| 506 | 450 |
| 507 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { | 451 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { |
| 508 // We can't close the pipe here, because calling OnChannelError | 452 // We can't close the pipe here, because calling OnChannelError |
| 509 // may destroy this object, and that would be bad if we are | 453 // may destroy this object, and that would be bad if we are |
| 510 // called from Send(). Instead, we return false and hope the | 454 // called from Send(). Instead, we return false and hope the |
| 511 // caller will close the pipe. If they do not, the pipe will | 455 // caller will close the pipe. If they do not, the pipe will |
| 512 // still be closed next time OnFileCanReadWithoutBlocking is | 456 // still be closed next time OnFileCanReadWithoutBlocking is |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection()); | 553 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection()); |
| 610 return IPC::GetPeerEuid(pipe_.get(), peer_euid); | 554 return IPC::GetPeerEuid(pipe_.get(), peer_euid); |
| 611 } | 555 } |
| 612 #endif | 556 #endif |
| 613 | 557 |
| 614 void ChannelPosix::ResetToAcceptingConnectionState() { | 558 void ChannelPosix::ResetToAcceptingConnectionState() { |
| 615 // Unregister libevent for the unix domain socket and close it. | 559 // Unregister libevent for the unix domain socket and close it. |
| 616 read_watcher_.StopWatchingFileDescriptor(); | 560 read_watcher_.StopWatchingFileDescriptor(); |
| 617 write_watcher_.StopWatchingFileDescriptor(); | 561 write_watcher_.StopWatchingFileDescriptor(); |
| 618 ResetSafely(&pipe_); | 562 ResetSafely(&pipe_); |
| 619 #if defined(IPC_USES_READWRITE) | |
| 620 fd_pipe_.reset(); | |
| 621 remote_fd_pipe_.reset(); | |
| 622 #endif // IPC_USES_READWRITE | |
| 623 | 563 |
| 624 while (!output_queue_.empty()) { | 564 while (!output_queue_.empty()) { |
| 625 Message* m = output_queue_.front(); | 565 Message* m = output_queue_.front(); |
| 626 output_queue_.pop(); | 566 output_queue_.pop(); |
| 627 delete m; | 567 delete m; |
| 628 } | 568 } |
| 629 | 569 |
| 630 // Close any outstanding, received file descriptors. | 570 // Close any outstanding, received file descriptors. |
| 631 ClearInputFDs(); | 571 ClearInputFDs(); |
| 632 | 572 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 791 } | 731 } |
| 792 | 732 |
| 793 void ChannelPosix::QueueHelloMessage() { | 733 void ChannelPosix::QueueHelloMessage() { |
| 794 // Create the Hello message | 734 // Create the Hello message |
| 795 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | 735 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, |
| 796 HELLO_MESSAGE_TYPE, | 736 HELLO_MESSAGE_TYPE, |
| 797 IPC::Message::PRIORITY_NORMAL)); | 737 IPC::Message::PRIORITY_NORMAL)); |
| 798 if (!msg->WriteInt(GetHelloMessageProcId())) { | 738 if (!msg->WriteInt(GetHelloMessageProcId())) { |
| 799 NOTREACHED() << "Unable to pickle hello message proc id"; | 739 NOTREACHED() << "Unable to pickle hello message proc id"; |
| 800 } | 740 } |
| 801 #if defined(IPC_USES_READWRITE) | |
| 802 scoped_ptr<Message> hello; | |
| 803 if (remote_fd_pipe_.is_valid()) { | |
| 804 if (!msg->WriteAttachment( | |
| 805 new internal::PlatformFileAttachment(remote_fd_pipe_.get()))) { | |
| 806 NOTREACHED() << "Unable to pickle hello message file descriptors"; | |
| 807 } | |
| 808 DCHECK_EQ(msg->attachment_set()->size(), 1U); | |
| 809 } | |
| 810 #endif // IPC_USES_READWRITE | |
| 811 output_queue_.push(msg.release()); | 741 output_queue_.push(msg.release()); |
| 812 } | 742 } |
| 813 | 743 |
| 814 ChannelPosix::ReadState ChannelPosix::ReadData( | 744 ChannelPosix::ReadState ChannelPosix::ReadData( |
| 815 char* buffer, | 745 char* buffer, |
| 816 int buffer_len, | 746 int buffer_len, |
| 817 int* bytes_read) { | 747 int* bytes_read) { |
| 818 if (!pipe_.is_valid()) | 748 if (!pipe_.is_valid()) |
| 819 return READ_FAILED; | 749 return READ_FAILED; |
| 820 | 750 |
| 821 struct msghdr msg = {0}; | 751 struct msghdr msg = {0}; |
| 822 | 752 |
| 823 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)}; | 753 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)}; |
| 824 msg.msg_iov = &iov; | 754 msg.msg_iov = &iov; |
| 825 msg.msg_iovlen = 1; | 755 msg.msg_iovlen = 1; |
| 826 | 756 |
| 827 msg.msg_control = input_cmsg_buf_; | 757 msg.msg_control = input_cmsg_buf_; |
| 828 | 758 |
| 829 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data | 759 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data |
| 830 // is waiting on the pipe. | 760 // is waiting on the pipe. |
| 831 #if defined(IPC_USES_READWRITE) | 761 msg.msg_controllen = sizeof(input_cmsg_buf_); |
| 832 if (fd_pipe_.is_valid()) { | 762 *bytes_read = HANDLE_EINTR(recvmsg(pipe_.get(), &msg, MSG_DONTWAIT)); |
| 833 *bytes_read = HANDLE_EINTR(read(pipe_.get(), buffer, buffer_len)); | 763 |
| 834 msg.msg_controllen = 0; | |
| 835 } else | |
| 836 #endif // IPC_USES_READWRITE | |
| 837 { | |
| 838 msg.msg_controllen = sizeof(input_cmsg_buf_); | |
| 839 *bytes_read = HANDLE_EINTR(recvmsg(pipe_.get(), &msg, MSG_DONTWAIT)); | |
| 840 } | |
| 841 if (*bytes_read < 0) { | 764 if (*bytes_read < 0) { |
| 842 if (errno == EAGAIN) { | 765 if (errno == EAGAIN) { |
| 843 return READ_PENDING; | 766 return READ_PENDING; |
| 844 #if defined(OS_MACOSX) | 767 #if defined(OS_MACOSX) |
| 845 } else if (errno == EPERM) { | 768 } else if (errno == EPERM) { |
| 846 // On OSX, reading from a pipe with no listener returns EPERM | 769 // On OSX, reading from a pipe with no listener returns EPERM |
| 847 // treat this as a special case to prevent spurious error messages | 770 // treat this as a special case to prevent spurious error messages |
| 848 // to the console. | 771 // to the console. |
| 849 return READ_FAILED; | 772 return READ_FAILED; |
| 850 #endif // OS_MACOSX | 773 #endif // OS_MACOSX |
| (...skipping 10 matching lines...) Expand all Loading... |
| 861 DCHECK(*bytes_read); | 784 DCHECK(*bytes_read); |
| 862 | 785 |
| 863 CloseClientFileDescriptor(); | 786 CloseClientFileDescriptor(); |
| 864 | 787 |
| 865 // Read any file descriptors from the message. | 788 // Read any file descriptors from the message. |
| 866 if (!ExtractFileDescriptorsFromMsghdr(&msg)) | 789 if (!ExtractFileDescriptorsFromMsghdr(&msg)) |
| 867 return READ_FAILED; | 790 return READ_FAILED; |
| 868 return READ_SUCCEEDED; | 791 return READ_SUCCEEDED; |
| 869 } | 792 } |
| 870 | 793 |
| 871 #if defined(IPC_USES_READWRITE) | |
| 872 bool ChannelPosix::ReadFileDescriptorsFromFDPipe() { | |
| 873 char dummy; | |
| 874 struct iovec fd_pipe_iov = { &dummy, 1 }; | |
| 875 | |
| 876 struct msghdr msg = { 0 }; | |
| 877 msg.msg_iov = &fd_pipe_iov; | |
| 878 msg.msg_iovlen = 1; | |
| 879 msg.msg_control = input_cmsg_buf_; | |
| 880 msg.msg_controllen = sizeof(input_cmsg_buf_); | |
| 881 ssize_t bytes_received = | |
| 882 HANDLE_EINTR(recvmsg(fd_pipe_.get(), &msg, MSG_DONTWAIT)); | |
| 883 | |
| 884 if (bytes_received != 1) | |
| 885 return true; // No message waiting. | |
| 886 | |
| 887 if (!ExtractFileDescriptorsFromMsghdr(&msg)) | |
| 888 return false; | |
| 889 return true; | |
| 890 } | |
| 891 #endif | |
| 892 | |
| 893 // On Posix, we need to fix up the file descriptors before the input message | 794 // On Posix, we need to fix up the file descriptors before the input message |
| 894 // is dispatched. | 795 // is dispatched. |
| 895 // | 796 // |
| 896 // This will read from the input_fds_ (READWRITE mode only) and read more | 797 // This will read from the input_fds_ (READWRITE mode only) and read more |
| 897 // handles from the FD pipe if necessary. | 798 // handles from the FD pipe if necessary. |
| 898 bool ChannelPosix::WillDispatchInputMessage(Message* msg) { | 799 bool ChannelPosix::WillDispatchInputMessage(Message* msg) { |
| 899 uint16 header_fds = msg->header()->num_fds; | 800 uint16 header_fds = msg->header()->num_fds; |
| 900 if (!header_fds) | 801 if (!header_fds) |
| 901 return true; // Nothing to do. | 802 return true; // Nothing to do. |
| 902 | 803 |
| 903 // The message has file descriptors. | 804 // The message has file descriptors. |
| 904 const char* error = NULL; | 805 const char* error = NULL; |
| 905 if (header_fds > input_fds_.size()) { | 806 if (header_fds > input_fds_.size()) { |
| 906 // The message has been completely received, but we didn't get | 807 // The message has been completely received, but we didn't get |
| 907 // enough file descriptors. | 808 // enough file descriptors. |
| 908 #if defined(IPC_USES_READWRITE) | 809 error = "Message needs unreceived descriptors"; |
| 909 if (!ReadFileDescriptorsFromFDPipe()) | |
| 910 return false; | |
| 911 if (header_fds > input_fds_.size()) | |
| 912 #endif // IPC_USES_READWRITE | |
| 913 error = "Message needs unreceived descriptors"; | |
| 914 } | 810 } |
| 915 | 811 |
| 916 if (header_fds > MessageAttachmentSet::kMaxDescriptorsPerMessage) | 812 if (header_fds > MessageAttachmentSet::kMaxDescriptorsPerMessage) |
| 917 error = "Message requires an excessive number of descriptors"; | 813 error = "Message requires an excessive number of descriptors"; |
| 918 | 814 |
| 919 if (error) { | 815 if (error) { |
| 920 LOG(WARNING) << error | 816 LOG(WARNING) << error |
| 921 << " channel:" << this | 817 << " channel:" << this |
| 922 << " message-type:" << msg->type() | 818 << " message-type:" << msg->type() |
| 923 << " header()->num_fds:" << header_fds; | 819 << " header()->num_fds:" << header_fds; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1010 switch (msg.type()) { | 906 switch (msg.type()) { |
| 1011 default: | 907 default: |
| 1012 NOTREACHED(); | 908 NOTREACHED(); |
| 1013 break; | 909 break; |
| 1014 | 910 |
| 1015 case Channel::HELLO_MESSAGE_TYPE: | 911 case Channel::HELLO_MESSAGE_TYPE: |
| 1016 int pid; | 912 int pid; |
| 1017 if (!iter.ReadInt(&pid)) | 913 if (!iter.ReadInt(&pid)) |
| 1018 NOTREACHED(); | 914 NOTREACHED(); |
| 1019 | 915 |
| 1020 #if defined(IPC_USES_READWRITE) | |
| 1021 if (mode_ & MODE_SERVER_FLAG) { | |
| 1022 // With IPC_USES_READWRITE, the Hello message from the client to the | |
| 1023 // server also contains the fd_pipe_, which will be used for all | |
| 1024 // subsequent file descriptor passing. | |
| 1025 DCHECK_EQ(msg.attachment_set()->size(), 1U); | |
| 1026 scoped_refptr<MessageAttachment> attachment; | |
| 1027 if (!msg.ReadAttachment(&iter, &attachment)) { | |
| 1028 NOTREACHED(); | |
| 1029 } | |
| 1030 fd_pipe_.reset(attachment->TakePlatformFile()); | |
| 1031 } | |
| 1032 #endif // IPC_USES_READWRITE | |
| 1033 peer_pid_ = pid; | 916 peer_pid_ = pid; |
| 1034 listener()->OnChannelConnected(pid); | 917 listener()->OnChannelConnected(pid); |
| 1035 break; | 918 break; |
| 1036 | 919 |
| 1037 #if defined(OS_MACOSX) | 920 #if defined(OS_MACOSX) |
| 1038 case Channel::CLOSE_FD_MESSAGE_TYPE: | 921 case Channel::CLOSE_FD_MESSAGE_TYPE: |
| 1039 int fd, hops; | 922 int fd, hops; |
| 1040 if (!iter.ReadInt(&hops)) | 923 if (!iter.ReadInt(&hops)) |
| 1041 NOTREACHED(); | 924 NOTREACHED(); |
| 1042 if (!iter.ReadInt(&fd)) | 925 if (!iter.ReadInt(&fd)) |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1122 // A random name is sufficient validation on posix systems, so we don't need | 1005 // A random name is sufficient validation on posix systems, so we don't need |
| 1123 // an additional shared secret. | 1006 // an additional shared secret. |
| 1124 | 1007 |
| 1125 std::string id = prefix; | 1008 std::string id = prefix; |
| 1126 if (!id.empty()) | 1009 if (!id.empty()) |
| 1127 id.append("."); | 1010 id.append("."); |
| 1128 | 1011 |
| 1129 return id.append(GenerateUniqueRandomChannelID()); | 1012 return id.append(GenerateUniqueRandomChannelID()); |
| 1130 } | 1013 } |
| 1131 | 1014 |
| 1132 | |
| 1133 bool Channel::IsNamedServerInitialized( | 1015 bool Channel::IsNamedServerInitialized( |
| 1134 const std::string& channel_id) { | 1016 const std::string& channel_id) { |
| 1135 return ChannelPosix::IsNamedServerInitialized(channel_id); | 1017 return ChannelPosix::IsNamedServerInitialized(channel_id); |
| 1136 } | 1018 } |
| 1137 | 1019 |
| 1138 #if defined(OS_LINUX) | 1020 #if defined(OS_LINUX) |
| 1139 // static | 1021 // static |
| 1140 void Channel::SetGlobalPid(int pid) { | 1022 void Channel::SetGlobalPid(int pid) { |
| 1141 ChannelPosix::SetGlobalPid(pid); | 1023 ChannelPosix::SetGlobalPid(pid); |
| 1142 } | 1024 } |
| 1143 #endif // OS_LINUX | 1025 #endif // OS_LINUX |
| 1144 | 1026 |
| 1145 } // namespace IPC | 1027 } // namespace IPC |
| OLD | NEW |