Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / socket / unix_domain_listen_socket_posix.cc
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.
4
5 #include "net/socket/unix_domain_listen_socket_posix.h"
6
7 #include <errno.h>
8 #include <sys/socket.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <sys/un.h>
12 #include <unistd.h>
13
14 #include <cstring>
15 #include <string>
16
17 #include "base/bind.h"
18 #include "base/callback.h"
19 #include "base/posix/eintr_wrapper.h"
20 #include "base/threading/platform_thread.h"
21 #include "build/build_config.h"
22 #include "net/base/net_errors.h"
23 #include "net/base/net_util.h"
24 #include "net/socket/socket_descriptor.h"
25 #include "net/socket/unix_domain_client_socket_posix.h"
26
27 namespace net {
28 namespace deprecated {
29
30 namespace {
31
32 int CreateAndBind(const std::string& socket_path,
33                   bool use_abstract_namespace,
34                   SocketDescriptor* socket_fd) {
35   DCHECK(socket_fd);
36
37   SockaddrStorage address;
38   if (!UnixDomainClientSocket::FillAddress(socket_path,
39                                            use_abstract_namespace,
40                                            &address)) {
41     return ERR_ADDRESS_INVALID;
42   }
43
44   SocketDescriptor fd = CreatePlatformSocket(PF_UNIX, SOCK_STREAM, 0);
45   if (fd == kInvalidSocket)
46     return errno ? MapSystemError(errno) : ERR_UNEXPECTED;
47
48   if (bind(fd, address.addr, address.addr_len) < 0) {
49     int rv = MapSystemError(errno);
50     close(fd);
51     PLOG(ERROR) << "Could not bind unix domain socket to " << socket_path
52                 << (use_abstract_namespace ? " (with abstract namespace)" : "");
53     return rv;
54   }
55
56   *socket_fd = fd;
57   return OK;
58 }
59
60 }  // namespace
61
62 // static
63 scoped_ptr<UnixDomainListenSocket>
64 UnixDomainListenSocket::CreateAndListenInternal(
65     const std::string& path,
66     const std::string& fallback_path,
67     StreamListenSocket::Delegate* del,
68     const AuthCallback& auth_callback,
69     bool use_abstract_namespace) {
70   SocketDescriptor socket_fd = kInvalidSocket;
71   int rv = CreateAndBind(path, use_abstract_namespace, &socket_fd);
72   if (rv != OK && !fallback_path.empty())
73     rv = CreateAndBind(fallback_path, use_abstract_namespace, &socket_fd);
74   if (rv != OK)
75     return scoped_ptr<UnixDomainListenSocket>();
76   scoped_ptr<UnixDomainListenSocket> sock(
77       new UnixDomainListenSocket(socket_fd, del, auth_callback));
78   sock->Listen();
79   return sock.Pass();
80 }
81
82 // static
83 scoped_ptr<UnixDomainListenSocket> UnixDomainListenSocket::CreateAndListen(
84     const std::string& path,
85     StreamListenSocket::Delegate* del,
86     const AuthCallback& auth_callback) {
87   return CreateAndListenInternal(path, "", del, auth_callback, false);
88 }
89
90 #if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED)
91 // static
92 scoped_ptr<UnixDomainListenSocket>
93 UnixDomainListenSocket::CreateAndListenWithAbstractNamespace(
94     const std::string& path,
95     const std::string& fallback_path,
96     StreamListenSocket::Delegate* del,
97     const AuthCallback& auth_callback) {
98   return
99       CreateAndListenInternal(path, fallback_path, del, auth_callback, true);
100 }
101 #endif
102
103 UnixDomainListenSocket::UnixDomainListenSocket(
104     SocketDescriptor s,
105     StreamListenSocket::Delegate* del,
106     const AuthCallback& auth_callback)
107     : StreamListenSocket(s, del),
108       auth_callback_(auth_callback) {}
109
110 UnixDomainListenSocket::~UnixDomainListenSocket() {}
111
112 void UnixDomainListenSocket::Accept() {
113   SocketDescriptor conn = StreamListenSocket::AcceptSocket();
114   if (conn == kInvalidSocket)
115     return;
116   UnixDomainServerSocket::Credentials credentials;
117   if (!UnixDomainServerSocket::GetPeerCredentials(conn, &credentials) ||
118       !auth_callback_.Run(credentials)) {
119     if (IGNORE_EINTR(close(conn)) < 0)
120       LOG(ERROR) << "close() error";
121     return;
122   }
123   scoped_ptr<UnixDomainListenSocket> sock(
124       new UnixDomainListenSocket(conn, socket_delegate_, auth_callback_));
125   // It's up to the delegate to AddRef if it wants to keep it around.
126   sock->WatchSocket(WAITING_READ);
127   socket_delegate_->DidAccept(this, sock.Pass());
128 }
129
130 UnixDomainListenSocketFactory::UnixDomainListenSocketFactory(
131     const std::string& path,
132     const UnixDomainListenSocket::AuthCallback& auth_callback)
133     : path_(path),
134       auth_callback_(auth_callback) {}
135
136 UnixDomainListenSocketFactory::~UnixDomainListenSocketFactory() {}
137
138 scoped_ptr<StreamListenSocket> UnixDomainListenSocketFactory::CreateAndListen(
139     StreamListenSocket::Delegate* delegate) const {
140   return UnixDomainListenSocket::CreateAndListen(
141              path_, delegate, auth_callback_).Pass();
142 }
143
144 #if defined(SOCKET_ABSTRACT_NAMESPACE_SUPPORTED)
145
146 UnixDomainListenSocketWithAbstractNamespaceFactory::
147 UnixDomainListenSocketWithAbstractNamespaceFactory(
148     const std::string& path,
149     const std::string& fallback_path,
150     const UnixDomainListenSocket::AuthCallback& auth_callback)
151     : UnixDomainListenSocketFactory(path, auth_callback),
152       fallback_path_(fallback_path) {}
153
154 UnixDomainListenSocketWithAbstractNamespaceFactory::
155 ~UnixDomainListenSocketWithAbstractNamespaceFactory() {}
156
157 scoped_ptr<StreamListenSocket>
158 UnixDomainListenSocketWithAbstractNamespaceFactory::CreateAndListen(
159     StreamListenSocket::Delegate* delegate) const {
160   return UnixDomainListenSocket::CreateAndListenWithAbstractNamespace(
161       path_, fallback_path_, delegate, auth_callback_);
162 }
163
164 #endif
165
166 }  // namespace deprecated
167 }  // namespace net