12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/ipc_channel_factory.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/file_util.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ipc/unix_domain_socket_util.h" 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace IPC { 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChannelFactory::ChannelFactory(const base::FilePath& path, Delegate* delegate) 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : path_(path), delegate_(delegate), listen_fd_(-1) { 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(delegate_); 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CreateSocket(); 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ChannelFactory::~ChannelFactory() { 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Close(); 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ChannelFactory::CreateSocket() { 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(listen_fd_ < 0); 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Create the socket. 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return CreateServerUnixDomainSocket(path_, &listen_fd_); 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ChannelFactory::Listen() { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (listen_fd_ < 0) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Watch the fd for connections, and turn any connections into 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // active sockets. 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForIO::current()->WatchFileDescriptor( 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listen_fd_, 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) true, 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForIO::WATCH_READ, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &server_listen_connection_watcher_, 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this); 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Called by libevent when we can read from the fd without blocking. 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChannelFactory::OnFileCanReadWithoutBlocking(int fd) { 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(fd == listen_fd_); 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int new_fd = -1; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ServerAcceptConnection(listen_fd_, &new_fd)) { 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Close(); 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->OnListenError(); 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_fd < 0) { 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The accept() failed, but not in such a way that the factory needs to be 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // shut down. 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) file_util::ScopedFD scoped_fd(&new_fd); 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Verify that the IPC channel peer is running as the same user. 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsPeerAuthorized(new_fd)) 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ChannelHandle handle(std::string(), 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FileDescriptor(*scoped_fd.release(), true)); 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->OnClientConnected(handle); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChannelFactory::OnFileCanWriteWithoutBlocking(int fd) { 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NOTREACHED() << "Listen fd should never be writable."; 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ChannelFactory::Close() { 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (listen_fd_ < 0) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (IGNORE_EINTR(close(listen_fd_)) < 0) 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "close"; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) listen_fd_ = -1; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (unlink(path_.value().c_str()) < 0) 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PLOG(ERROR) << "unlink"; 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Unregister libevent for the listening socket and close it. 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) server_listen_connection_watcher_.StopWatchingFileDescriptor(); 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace IPC 90