diff options
author | jeremya@chromium.org <jeremya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-11 04:17:17 +0000 |
---|---|---|
committer | jeremya@chromium.org <jeremya@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-11 04:17:17 +0000 |
commit | 3cfcda39679d94a12a7494dd4a73dc32c37dfce8 (patch) | |
tree | 5bd4ea646b094f481d183552bc3b924dd5b3a8ba /ipc/ipc_channel_factory.cc | |
parent | 8e97f014e47198ff1475bc5e9c57e4280a8bc18c (diff) | |
download | chromium_src-3cfcda39679d94a12a7494dd4a73dc32c37dfce8.zip chromium_src-3cfcda39679d94a12a7494dd4a73dc32c37dfce8.tar.gz chromium_src-3cfcda39679d94a12a7494dd4a73dc32c37dfce8.tar.bz2 |
Implement IPC::ChannelFactory, a class that accept()s on a UNIX socket.
IPC::ChannelFactory listens on a UNIX domain socket and notifies its delegate
when a client connects. The delegate is expected to craft an IPC::Channel from
the handle it is given.
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=186912
Review URL: https://chromiumcodereview.appspot.com/12386010
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@187233 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ipc/ipc_channel_factory.cc')
-rw-r--r-- | ipc/ipc_channel_factory.cc | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/ipc/ipc_channel_factory.cc b/ipc/ipc_channel_factory.cc new file mode 100644 index 0000000..d355328 --- /dev/null +++ b/ipc/ipc_channel_factory.cc @@ -0,0 +1,88 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ipc/ipc_channel_factory.h" + +#include "base/file_util.h" +#include "base/logging.h" +#include "ipc/unix_domain_socket_util.h" + +namespace IPC { + +ChannelFactory::ChannelFactory(const base::FilePath& path, Delegate* delegate) + : path_(path), delegate_(delegate), listen_fd_(-1) { + DCHECK(delegate_); + CreateSocket(); +} + +ChannelFactory::~ChannelFactory() { + Close(); +} + +bool ChannelFactory::CreateSocket() { + DCHECK(listen_fd_ < 0); + + // Create the socket. + return CreateServerUnixDomainSocket(path_, &listen_fd_); +} + +bool ChannelFactory::Listen() { + if (listen_fd_ < 0) + return false; + + // Watch the fd for connections, and turn any connections into + // active sockets. + MessageLoopForIO::current()->WatchFileDescriptor( + listen_fd_, + true, + MessageLoopForIO::WATCH_READ, + &server_listen_connection_watcher_, + this); + return true; +} + +// Called by libevent when we can read from the fd without blocking. +void ChannelFactory::OnFileCanReadWithoutBlocking(int fd) { + DCHECK(fd == listen_fd_); + int new_fd = -1; + if (!ServerAcceptConnection(listen_fd_, &new_fd)) { + Close(); + delegate_->OnListenError(); + return; + } + + if (new_fd < 0) { + // The accept() failed, but not in such a way that the factory needs to be + // shut down. + return; + } + + file_util::ScopedFD scoped_fd(&new_fd); + + // Verify that the IPC channel peer is running as the same user. + if (!IsPeerAuthorized(new_fd)) + return; + + ChannelHandle handle("", base::FileDescriptor(*scoped_fd.release(), true)); + delegate_->OnClientConnected(handle); +} + +void ChannelFactory::OnFileCanWriteWithoutBlocking(int fd) { + NOTREACHED() << "Listen fd should never be writable."; +} + +void ChannelFactory::Close() { + if (listen_fd_ < 0) + return; + if (HANDLE_EINTR(close(listen_fd_)) < 0) + PLOG(ERROR) << "close"; + listen_fd_ = -1; + if (unlink(path_.value().c_str()) < 0) + PLOG(ERROR) << "unlink"; + + // Unregister libevent for the listening socket and close it. + server_listen_connection_watcher_.StopWatchingFileDescriptor(); +} + +} // namespace IPC |