15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/apps/app_shim/unix_domain_socket_acceptor.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/scoped_file.h" 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/logging.h" 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ipc/unix_domain_socket_util.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace apps { 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UnixDomainSocketAcceptor::UnixDomainSocketAcceptor(const base::FilePath& path, 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Delegate* delegate) 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : path_(path), delegate_(delegate), listen_fd_(-1) { 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(delegate_); 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CreateSocket(); 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)UnixDomainSocketAcceptor::~UnixDomainSocketAcceptor() { 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Close(); 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UnixDomainSocketAcceptor::CreateSocket() { 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(listen_fd_ < 0); 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Create the socket. 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return IPC::CreateServerUnixDomainSocket(path_, &listen_fd_); 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool UnixDomainSocketAcceptor::Listen() { 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (listen_fd_ < 0) 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Watch the fd for connections, and turn any connections into 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // active sockets. 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoopForIO::current()->WatchFileDescriptor( 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) listen_fd_, 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) true, 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::MessageLoopForIO::WATCH_READ, 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &server_listen_connection_watcher_, 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this); 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Called by libevent when we can read from the fd without blocking. 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void UnixDomainSocketAcceptor::OnFileCanReadWithoutBlocking(int fd) { 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(fd == listen_fd_); 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int new_fd = -1; 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!IPC::ServerAcceptConnection(listen_fd_, &new_fd)) { 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Close(); 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_->OnListenError(); 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::ScopedFD scoped_fd(new_fd); 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!scoped_fd.is_valid()) { 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The accept() failed, but not in such a way that the factory needs to be 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // shut down. 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Verify that the IPC channel peer is running as the same user. 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!IPC::IsPeerAuthorized(scoped_fd.get())) 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPC::ChannelHandle handle(std::string(), 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::FileDescriptor(scoped_fd.release(), true)); 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delegate_->OnClientConnected(handle); 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void UnixDomainSocketAcceptor::OnFileCanWriteWithoutBlocking(int fd) { 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NOTREACHED() << "Listen fd should never be writable."; 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void UnixDomainSocketAcceptor::Close() { 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (listen_fd_ < 0) 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (IGNORE_EINTR(close(listen_fd_)) < 0) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PLOG(ERROR) << "close"; 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) listen_fd_ = -1; 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (unlink(path_.value().c_str()) < 0) 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PLOG(ERROR) << "unlink"; 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Unregister libevent for the listening socket and close it. 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) server_listen_connection_watcher_.StopWatchingFileDescriptor(); 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace apps 91