Adding Baseframework of the ResourceManager (all hooks and observers)
[chromium-blink-merge.git] / net / socket / unix_domain_server_socket_posix.cc
blob4ab0b834e624e81c94da14cc9dae2048b2d49ed0
1 // Copyright 2014 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.
5 #include "net/socket/unix_domain_server_socket_posix.h"
7 #include <errno.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <unistd.h>
12 #include "base/logging.h"
13 #include "net/base/net_errors.h"
14 #include "net/socket/socket_libevent.h"
15 #include "net/socket/unix_domain_client_socket_posix.h"
17 namespace net {
19 UnixDomainServerSocket::UnixDomainServerSocket(
20 const AuthCallback& auth_callback,
21 bool use_abstract_namespace)
22 : auth_callback_(auth_callback),
23 use_abstract_namespace_(use_abstract_namespace) {
24 DCHECK(!auth_callback_.is_null());
27 UnixDomainServerSocket::~UnixDomainServerSocket() {
30 // static
31 bool UnixDomainServerSocket::GetPeerCredentials(SocketDescriptor socket,
32 Credentials* credentials) {
33 #if defined(OS_LINUX) || defined(OS_ANDROID)
34 struct ucred user_cred;
35 socklen_t len = sizeof(user_cred);
36 if (getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &user_cred, &len) < 0)
37 return false;
38 credentials->process_id = user_cred.pid;
39 credentials->user_id = user_cred.uid;
40 credentials->group_id = user_cred.gid;
41 return true;
42 #else
43 return getpeereid(
44 socket, &credentials->user_id, &credentials->group_id) == 0;
45 #endif
48 int UnixDomainServerSocket::Listen(const IPEndPoint& address, int backlog) {
49 NOTIMPLEMENTED();
50 return ERR_NOT_IMPLEMENTED;
53 int UnixDomainServerSocket::ListenWithAddressAndPort(
54 const std::string& unix_domain_path,
55 int port_unused,
56 int backlog) {
57 DCHECK(!listen_socket_);
59 SockaddrStorage address;
60 if (!UnixDomainClientSocket::FillAddress(unix_domain_path,
61 use_abstract_namespace_,
62 &address)) {
63 return ERR_ADDRESS_INVALID;
66 scoped_ptr<SocketLibevent> socket(new SocketLibevent);
67 int rv = socket->Open(AF_UNIX);
68 DCHECK_NE(ERR_IO_PENDING, rv);
69 if (rv != OK)
70 return rv;
72 rv = socket->Bind(address);
73 DCHECK_NE(ERR_IO_PENDING, rv);
74 if (rv != OK) {
75 PLOG(ERROR)
76 << "Could not bind unix domain socket to " << unix_domain_path
77 << (use_abstract_namespace_ ? " (with abstract namespace)" : "");
78 return rv;
81 rv = socket->Listen(backlog);
82 DCHECK_NE(ERR_IO_PENDING, rv);
83 if (rv != OK)
84 return rv;
86 listen_socket_.swap(socket);
87 return rv;
90 int UnixDomainServerSocket::GetLocalAddress(IPEndPoint* address) const {
91 NOTIMPLEMENTED();
92 return ERR_NOT_IMPLEMENTED;
95 int UnixDomainServerSocket::Accept(scoped_ptr<StreamSocket>* socket,
96 const CompletionCallback& callback) {
97 DCHECK(socket);
98 DCHECK(!callback.is_null());
99 DCHECK(listen_socket_);
100 DCHECK(!accept_socket_);
102 while (true) {
103 int rv = listen_socket_->Accept(
104 &accept_socket_,
105 base::Bind(&UnixDomainServerSocket::AcceptCompleted,
106 base::Unretained(this), socket, callback));
107 if (rv != OK)
108 return rv;
109 if (AuthenticateAndGetStreamSocket(socket))
110 return OK;
111 // Accept another socket because authentication error should be transparent
112 // to the caller.
116 void UnixDomainServerSocket::AcceptCompleted(scoped_ptr<StreamSocket>* socket,
117 const CompletionCallback& callback,
118 int rv) {
119 if (rv != OK) {
120 callback.Run(rv);
121 return;
124 if (AuthenticateAndGetStreamSocket(socket)) {
125 callback.Run(OK);
126 return;
129 // Accept another socket because authentication error should be transparent
130 // to the caller.
131 rv = Accept(socket, callback);
132 if (rv != ERR_IO_PENDING)
133 callback.Run(rv);
136 bool UnixDomainServerSocket::AuthenticateAndGetStreamSocket(
137 scoped_ptr<StreamSocket>* socket) {
138 DCHECK(accept_socket_);
140 Credentials credentials;
141 if (!GetPeerCredentials(accept_socket_->socket_fd(), &credentials) ||
142 !auth_callback_.Run(credentials)) {
143 accept_socket_.reset();
144 return false;
147 socket->reset(new UnixDomainClientSocket(accept_socket_.Pass()));
148 return true;
151 } // namespace net