• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ipc/ipc_channel_factory.h"
6 
7 #include "base/file_util.h"
8 #include "base/files/scoped_file.h"
9 #include "base/logging.h"
10 #include "ipc/unix_domain_socket_util.h"
11 
12 namespace IPC {
13 
ChannelFactory(const base::FilePath & path,Delegate * delegate)14 ChannelFactory::ChannelFactory(const base::FilePath& path, Delegate* delegate)
15     : path_(path), delegate_(delegate), listen_fd_(-1) {
16   DCHECK(delegate_);
17   CreateSocket();
18 }
19 
~ChannelFactory()20 ChannelFactory::~ChannelFactory() {
21   Close();
22 }
23 
CreateSocket()24 bool ChannelFactory::CreateSocket() {
25   DCHECK(listen_fd_ < 0);
26 
27   // Create the socket.
28   return CreateServerUnixDomainSocket(path_, &listen_fd_);
29 }
30 
Listen()31 bool ChannelFactory::Listen() {
32   if (listen_fd_ < 0)
33     return false;
34 
35   // Watch the fd for connections, and turn any connections into
36   // active sockets.
37   base::MessageLoopForIO::current()->WatchFileDescriptor(
38       listen_fd_,
39       true,
40       base::MessageLoopForIO::WATCH_READ,
41       &server_listen_connection_watcher_,
42       this);
43   return true;
44 }
45 
46 // Called by libevent when we can read from the fd without blocking.
OnFileCanReadWithoutBlocking(int fd)47 void ChannelFactory::OnFileCanReadWithoutBlocking(int fd) {
48   DCHECK(fd == listen_fd_);
49   int new_fd = -1;
50   if (!ServerAcceptConnection(listen_fd_, &new_fd)) {
51     Close();
52     delegate_->OnListenError();
53     return;
54   }
55   base::ScopedFD scoped_fd(new_fd);
56 
57   if (!scoped_fd.is_valid()) {
58     // The accept() failed, but not in such a way that the factory needs to be
59     // shut down.
60     return;
61   }
62 
63   // Verify that the IPC channel peer is running as the same user.
64   if (!IsPeerAuthorized(scoped_fd.get()))
65     return;
66 
67   ChannelHandle handle(std::string(),
68                        base::FileDescriptor(scoped_fd.release(), true));
69   delegate_->OnClientConnected(handle);
70 }
71 
OnFileCanWriteWithoutBlocking(int fd)72 void ChannelFactory::OnFileCanWriteWithoutBlocking(int fd) {
73   NOTREACHED() << "Listen fd should never be writable.";
74 }
75 
Close()76 void ChannelFactory::Close() {
77   if (listen_fd_ < 0)
78     return;
79   if (IGNORE_EINTR(close(listen_fd_)) < 0)
80     PLOG(ERROR) << "close";
81   listen_fd_ = -1;
82   if (unlink(path_.value().c_str()) < 0)
83     PLOG(ERROR) << "unlink";
84 
85   // Unregister libevent for the listening socket and close it.
86   server_listen_connection_watcher_.StopWatchingFileDescriptor();
87 }
88 
89 }  // namespace IPC
90