Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(699)

Unified Diff: net/socket/unix_domain_server_socket_posix.cc

Issue 376323002: Refactor unix domain socket. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Moved UnixDomainListenSocket to net::deprecated namespace. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/socket/unix_domain_server_socket_posix.cc
diff --git a/net/socket/unix_domain_server_socket_posix.cc b/net/socket/unix_domain_server_socket_posix.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8f2f2d6de2f01e4bffa0758b22edea5c96489455
--- /dev/null
+++ b/net/socket/unix_domain_server_socket_posix.cc
@@ -0,0 +1,145 @@
+// 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 "net/socket/unix_domain_server_socket_posix.h"
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "base/logging.h"
+#include "net/base/net_errors.h"
+#include "net/socket/socket_libevent.h"
+#include "net/socket/unix_domain_client_socket_posix.h"
+
+namespace net {
+
+UnixDomainServerSocket::UnixDomainServerSocket(
+ const AuthCallback& auth_callback,
+ bool use_abstract_namespace)
+ : auth_callback_(auth_callback),
+ use_abstract_namespace_(use_abstract_namespace) {
+ DCHECK(!auth_callback_.is_null());
+}
+
+UnixDomainServerSocket::~UnixDomainServerSocket() {
+}
+
+// static
+bool UnixDomainServerSocket::GetPeerIds(SocketDescriptor socket,
+ uid_t* user_id,
+ gid_t* group_id) {
+#if defined(OS_LINUX) || defined(OS_ANDROID)
+ struct ucred user_cred;
+ socklen_t len = sizeof(user_cred);
+ if (getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &user_cred, &len) < 0)
+ return false;
+ *user_id = user_cred.uid;
+ *group_id = user_cred.gid;
+ return true;
+#else
+ return getpeereid(socket, user_id, group_id) == 0;
+#endif
+}
+
+int UnixDomainServerSocket::Listen(const IPEndPoint& address, int backlog) {
+ NOTIMPLEMENTED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+int UnixDomainServerSocket::ListenWithAddressAndPort(
+ const std::string& unix_domain_path,
+ int port_unused,
+ int backlog) {
+ DCHECK(!listen_socket_);
+
+ SockaddrStorage address;
+ if (!UnixDomainClientSocket::FillAddress(unix_domain_path,
+ use_abstract_namespace_,
+ &address)) {
+ return ERR_ADDRESS_INVALID;
+ }
+
+ listen_socket_.reset(new SocketLibevent);
+ int rv = listen_socket_->Open(AF_UNIX);
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ if (rv != OK)
+ return rv;
+
+ rv = listen_socket_->Bind(address);
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ if (rv != OK) {
+ PLOG(ERROR)
+ << "Could not bind unix domain socket to " << unix_domain_path
+ << (use_abstract_namespace_ ? " (with abstract namespace)" : "");
+ return rv;
+ }
+
+ return listen_socket_->Listen(backlog);
+}
+
+int UnixDomainServerSocket::GetLocalAddress(IPEndPoint* address) const {
+ NOTIMPLEMENTED();
+ return ERR_NOT_IMPLEMENTED;
+}
+
+int UnixDomainServerSocket::Accept(scoped_ptr<StreamSocket>* socket,
+ const CompletionCallback& callback) {
+ DCHECK(socket);
+ DCHECK(!callback.is_null());
+ DCHECK(listen_socket_);
+ DCHECK(!accept_socket_);
+
+ while (true) {
+ int rv = listen_socket_->Accept(
+ &accept_socket_,
+ base::Bind(&UnixDomainServerSocket::AcceptCompleted,
+ base::Unretained(this), socket, callback));
+ if (rv != OK)
+ return rv;
+ if (AuthenticateAndGetStreamSocket(socket))
+ return OK;
+ // Accept another socket because authentication error should be transparent
+ // to the caller.
+ }
+}
+
+void UnixDomainServerSocket::AcceptCompleted(scoped_ptr<StreamSocket>* socket,
+ const CompletionCallback& callback,
+ int rv) {
+ if (rv != OK) {
+ callback.Run(rv);
+ return;
+ }
+
+ if (AuthenticateAndGetStreamSocket(socket)) {
+ callback.Run(OK);
+ return;
+ }
+
+ // Accept another socket because authentication error should be transparent
+ // to the caller.
+ rv = Accept(socket, callback);
+ if (rv != ERR_IO_PENDING)
+ callback.Run(rv);
+}
+
+bool UnixDomainServerSocket::AuthenticateAndGetStreamSocket(
+ scoped_ptr<StreamSocket>* socket) {
+ DCHECK(accept_socket_);
+
+ uid_t user_id;
+ gid_t group_id;
+ if (!GetPeerIds(accept_socket_->socket_fd(), &user_id, &group_id) ||
+ !auth_callback_.Run(user_id, group_id)) {
+ accept_socket_.reset();
+ return false;
+ }
+
+ socket->reset(new UnixDomainClientSocket(accept_socket_.Pass()));
+ return true;
+}
+
+} // namespace net
« no previous file with comments | « net/socket/unix_domain_server_socket_posix.h ('k') | net/socket/unix_domain_server_socket_posix_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698