Chromium Code Reviews| Index: mojo/shell/incoming_connection_listener.cc |
| diff --git a/mojo/shell/incoming_connection_listener.cc b/mojo/shell/incoming_connection_listener.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..24dc3e58901f57eb3909b57b68813068fd8a3202 |
| --- /dev/null |
| +++ b/mojo/shell/incoming_connection_listener.cc |
| @@ -0,0 +1,110 @@ |
| +// Copyright 2014 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 "mojo/shell/incoming_connection_listener.h" |
| + |
| +#include "base/callback.h" |
| +#include "base/files/file_path.h" |
| +#include "base/files/file_util.h" |
| +#include "base/logging.h" |
| +#include "base/memory/scoped_ptr.h" |
| +#include "base/sequenced_task_runner.h" |
| +#include "base/tracked_objects.h" |
| +#include "net/base/net_errors.h" |
| +#include "net/socket/socket_descriptor.h" |
| +#include "net/socket/unix_domain_server_socket_posix.h" |
| + |
| +namespace mojo { |
| +namespace shell { |
| + |
| +namespace { |
| +// TODO(cmasone): Figure out what we should be doing about "authenticating" the |
| +// process trying to connect. |
| +bool Yes(const net::UnixDomainServerSocket::Credentials& ignored) { |
| + return true; |
| +} |
| +} // anonymous namespace |
| + |
| +IncomingConnectionListener::Delegate::Delegate() { |
| +} |
| + |
| +IncomingConnectionListener::Delegate::~Delegate() { |
| +} |
| + |
| +IncomingConnectionListener::IncomingConnectionListener( |
| + const base::FilePath& socket_path, |
| + Delegate* delegate) |
| + : delegate_(delegate), |
| + socket_path_(socket_path), |
| + listen_socket_(base::Bind(&Yes), false), |
| + incoming_socket_(net::kInvalidSocket), |
| + weak_ptr_factory_(this) { |
| + DCHECK(delegate_); |
| +} |
| + |
| +IncomingConnectionListener::~IncomingConnectionListener() { |
| + weak_ptr_factory_.InvalidateWeakPtrs(); |
| + if (!base::DeleteFile(socket_path_, false)) |
| + PLOG(ERROR) << "Listening Unix domain socket can't be destroyed."; |
| +} |
| + |
| +void IncomingConnectionListener::StartListening() { |
| + DCHECK(listen_thread_checker_.CalledOnValidThread()); |
| + |
| + int rv = net::OK; |
| + if (base::PathExists(socket_path_)) { |
| + LOG(ERROR) << "Listening socket file already exists."; |
| + rv = net::ERR_FILE_EXISTS; |
| + } else if (!base::DirectoryExists(socket_path_.DirName())) { |
| + LOG(ERROR) << "Directorty for listening socket does not exist."; |
| + rv = net::ERR_FILE_NOT_FOUND; |
| + } else if (!base::PathIsWritable(socket_path_.DirName())) { |
| + LOG(ERROR) << "Listening socket file path is not writable."; |
| + rv = net::ERR_ACCESS_DENIED; |
| + } else { |
| + const std::string& socket_address = socket_path_.value(); |
| + rv = listen_socket_.ListenWithAddressAndPort(socket_address, 0, 100); |
| + } |
| + |
| + // Call OnListening() before Accept(), so that the delegate is certain to |
| + // hear about listening before a connection might be accepted below. |
| + delegate_->OnListening(rv); |
| + if (rv == net::OK) { |
|
DaveMoore
2014/09/26 22:48:57
Nit: no braces
Chris Masone
2014/09/27 00:46:30
Done.
|
| + Accept(); |
| + } |
| +} |
| + |
| +void IncomingConnectionListener::Accept() { |
| + DCHECK(listen_thread_checker_.CalledOnValidThread()); |
| + int rv = listen_socket_.AcceptSocketDescriptor( |
| + &incoming_socket_, |
| + base::Bind(&IncomingConnectionListener::OnAccept, |
| + weak_ptr_factory_.GetWeakPtr())); |
| + |
| + // If rv == net::ERR_IO_PENDING), listen_socket_ will call |
| + // OnAccept() later, when a connection attempt comes in. |
| + if (rv != net::ERR_IO_PENDING) { |
| + DVLOG_IF(1, rv == net::OK) << "Accept succeeded immediately"; |
| + OnAccept(rv); |
| + } |
| +} |
| + |
| +void IncomingConnectionListener::OnAccept(int rv) { |
| + DCHECK(listen_thread_checker_.CalledOnValidThread()); |
| + |
| + if (rv != net::OK || incoming_socket_ == net::kInvalidSocket) { |
| + LOG_IF(ERROR, rv != net::OK) << "Accept failed " << net::ErrorToString(rv); |
| + PLOG_IF(ERROR, rv == net::OK) << "Socket invalid"; |
| + } else { |
| + // Passes ownership of incoming_socket_ to delegate_. |
| + delegate_->OnConnection(incoming_socket_); |
| + incoming_socket_ = net::kInvalidSocket; |
| + } |
| + |
| + // Continue waiting to accept incoming connections... |
| + Accept(); |
| +} |
| + |
| +} // namespace shell |
| +} // namespace mojo |