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"
8 #include <sys/socket.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"
21 // Intended for use as SetterCallbacks in Accept() helper methods.
22 void SetStreamSocket(scoped_ptr
<StreamSocket
>* socket
,
23 scoped_ptr
<SocketLibevent
> accepted_socket
) {
24 socket
->reset(new UnixDomainClientSocket(accepted_socket
.Pass()));
27 void SetSocketDescriptor(SocketDescriptor
* socket
,
28 scoped_ptr
<SocketLibevent
> accepted_socket
) {
29 *socket
= accepted_socket
->ReleaseConnectedSocket();
32 } // anonymous namespace
34 UnixDomainServerSocket::UnixDomainServerSocket(
35 const AuthCallback
& auth_callback
,
36 bool use_abstract_namespace
)
37 : auth_callback_(auth_callback
),
38 use_abstract_namespace_(use_abstract_namespace
) {
39 DCHECK(!auth_callback_
.is_null());
42 UnixDomainServerSocket::~UnixDomainServerSocket() {
46 bool UnixDomainServerSocket::GetPeerCredentials(SocketDescriptor socket
,
47 Credentials
* credentials
) {
48 #if defined(OS_LINUX) || defined(OS_ANDROID)
49 struct ucred user_cred
;
50 socklen_t len
= sizeof(user_cred
);
51 if (getsockopt(socket
, SOL_SOCKET
, SO_PEERCRED
, &user_cred
, &len
) < 0)
53 credentials
->process_id
= user_cred
.pid
;
54 credentials
->user_id
= user_cred
.uid
;
55 credentials
->group_id
= user_cred
.gid
;
59 socket
, &credentials
->user_id
, &credentials
->group_id
) == 0;
63 int UnixDomainServerSocket::Listen(const IPEndPoint
& address
, int backlog
) {
65 return ERR_NOT_IMPLEMENTED
;
68 int UnixDomainServerSocket::ListenWithAddressAndPort(
69 const std::string
& unix_domain_path
,
72 DCHECK(!listen_socket_
);
74 SockaddrStorage address
;
75 if (!UnixDomainClientSocket::FillAddress(unix_domain_path
,
76 use_abstract_namespace_
,
78 return ERR_ADDRESS_INVALID
;
81 scoped_ptr
<SocketLibevent
> socket(new SocketLibevent
);
82 int rv
= socket
->Open(AF_UNIX
);
83 DCHECK_NE(ERR_IO_PENDING
, rv
);
87 rv
= socket
->Bind(address
);
88 DCHECK_NE(ERR_IO_PENDING
, rv
);
91 << "Could not bind unix domain socket to " << unix_domain_path
92 << (use_abstract_namespace_
? " (with abstract namespace)" : "");
96 rv
= socket
->Listen(backlog
);
97 DCHECK_NE(ERR_IO_PENDING
, rv
);
101 listen_socket_
.swap(socket
);
105 int UnixDomainServerSocket::GetLocalAddress(IPEndPoint
* address
) const {
108 // Unix domain sockets have no valid associated addr/port;
109 // return address invalid.
110 return ERR_ADDRESS_INVALID
;
113 int UnixDomainServerSocket::Accept(scoped_ptr
<StreamSocket
>* socket
,
114 const CompletionCallback
& callback
) {
117 SetterCallback setter_callback
= base::Bind(&SetStreamSocket
, socket
);
118 return DoAccept(setter_callback
, callback
);
121 int UnixDomainServerSocket::AcceptSocketDescriptor(
122 SocketDescriptor
* socket
,
123 const CompletionCallback
& callback
) {
126 SetterCallback setter_callback
= base::Bind(&SetSocketDescriptor
, socket
);
127 return DoAccept(setter_callback
, callback
);
130 int UnixDomainServerSocket::DoAccept(const SetterCallback
& setter_callback
,
131 const CompletionCallback
& callback
) {
132 DCHECK(!setter_callback
.is_null());
133 DCHECK(!callback
.is_null());
134 DCHECK(listen_socket_
);
135 DCHECK(!accept_socket_
);
138 int rv
= listen_socket_
->Accept(
140 base::Bind(&UnixDomainServerSocket::AcceptCompleted
,
141 base::Unretained(this),
146 if (AuthenticateAndGetStreamSocket(setter_callback
))
148 // Accept another socket because authentication error should be transparent
153 void UnixDomainServerSocket::AcceptCompleted(
154 const SetterCallback
& setter_callback
,
155 const CompletionCallback
& callback
,
162 if (AuthenticateAndGetStreamSocket(setter_callback
)) {
167 // Accept another socket because authentication error should be transparent
169 rv
= DoAccept(setter_callback
, callback
);
170 if (rv
!= ERR_IO_PENDING
)
174 bool UnixDomainServerSocket::AuthenticateAndGetStreamSocket(
175 const SetterCallback
& setter_callback
) {
176 DCHECK(accept_socket_
);
178 Credentials credentials
;
179 if (!GetPeerCredentials(accept_socket_
->socket_fd(), &credentials
) ||
180 !auth_callback_
.Run(credentials
)) {
181 accept_socket_
.reset();
185 setter_callback
.Run(accept_socket_
.Pass());