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

Side by Side Diff: net/socket/unix_domain_server_socket_posix.cc

Issue 296053012: Replace StreamListenSocket with StreamSocket in HttpServer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Don't export HttpServer which is built in a static lib Created 6 years, 6 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 unified diff | Download patch
OLDNEW
(Empty)
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_server_socket_posix.h"
6
7 #include <errno.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <unistd.h>
11
12 #include "base/callback.h"
13 #include "base/callback_helpers.h"
14 #include "base/posix/eintr_wrapper.h"
15 #include "net/base/net_errors.h"
16 #include "net/socket/unix_domain_client_socket_posix.h"
17
18 namespace net {
19
20 UnixDomainServerSocket::UnixDomainServerSocket(
21 const AuthCallback& auth_callback,
22 bool use_abstract_namespace)
23 : socket_fd_(kInvalidSocket),
24 auth_callback_(auth_callback),
25 use_abstract_namespace_(use_abstract_namespace) {
26 }
27
28 UnixDomainServerSocket::~UnixDomainServerSocket() {
29 Close();
30 }
31
32 // static
33 int UnixDomainServerSocket::CreateAndBind(const std::string& socket_path,
34 bool use_abstract_namespace,
35 SocketDescriptor* socket_fd) {
36 sockaddr_un addr;
37 socklen_t addr_len = sizeof(addr);
38 if (!UnixDomainClientSocket::FillAddress(socket_path,
39 use_abstract_namespace,
40 &addr, &addr_len))
41 return ERR_ADDRESS_INVALID;
42
43 SocketDescriptor s = CreatePlatformSocket(PF_UNIX, SOCK_STREAM, 0);
44 if (s == kInvalidSocket)
45 return errno ? MapSystemError(errno) : ERR_UNEXPECTED;
46
47 if (bind(s, reinterpret_cast<sockaddr*>(&addr), addr_len) < 0) {
48 int rv = MapSystemError(errno);
49 close(s);
50 PLOG(ERROR) << "Could not bind unix domain socket to " << socket_path
51 << (use_abstract_namespace ? " (with abstract namespace)" : "");
52 return rv;
53 }
54
55 DCHECK(socket_fd);
56 *socket_fd = s;
57 return OK;
58 }
59
60 // static
61 bool UnixDomainServerSocket::GetPeerIds(SocketDescriptor socket,
62 uid_t* user_id,
63 gid_t* group_id) {
64 #if defined(OS_LINUX) || defined(OS_ANDROID)
65 struct ucred user_cred;
66 socklen_t len = sizeof(user_cred);
67 if (getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &user_cred, &len) < 0)
68 return false;
69 *user_id = user_cred.uid;
70 *group_id = user_cred.gid;
71 #else
72 if (getpeereid(socket, user_id, group_id) < 0)
73 return false;
74 #endif
75 return true;
76 }
77
78 void UnixDomainServerSocket::Close() {
79 if (socket_fd_ == kInvalidSocket)
80 return;
81 close(socket_fd_);
82 socket_fd_ = kInvalidSocket;
83 }
84
85 int UnixDomainServerSocket::Listen(const IPEndPoint& address, int backlog) {
86 NOTIMPLEMENTED();
87 return ERR_NOT_IMPLEMENTED;
88 }
89
90 int UnixDomainServerSocket::ListenWithAddressAndPort(
91 const std::string& unix_domain_path,
92 int port_unused,
93 int backlog) {
94 int rv = CreateAndBind(unix_domain_path,
95 use_abstract_namespace_,
96 &socket_fd_);
97 if (rv != OK)
98 return rv;
99
100 if (listen(socket_fd_, backlog) < 0) {
101 PLOG(ERROR) << "listen() returned an error";
102 rv = MapSystemError(errno);
103 Close();
104 return rv;
105 }
106
107 if (SetNonBlocking(socket_fd_)) {
108 rv = MapSystemError(errno);
109 Close();
110 return rv;
111 }
112
113 return OK;
114 }
115
116 int UnixDomainServerSocket::GetLocalAddress(IPEndPoint* address) const {
117 NOTIMPLEMENTED();
118 return ERR_NOT_IMPLEMENTED;
119 }
120
121 int UnixDomainServerSocket::Accept(scoped_ptr<StreamSocket>* socket,
122 const CompletionCallback& callback) {
123 DCHECK(socket);
124 DCHECK(!callback.is_null());
125 DCHECK(accept_callback_.is_null());
126
127 int rv = DoAccept(socket);
128 if (rv != ERR_IO_PENDING)
129 return rv;
130
131 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
132 socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
133 &accept_socket_watcher_, this)) {
134 PLOG(ERROR) << "WatchFileDescriptor failed on read";
135 return MapSystemError(errno);
136 }
137
138 accept_socket_ = socket;
139 accept_callback_ = callback;
140 return ERR_IO_PENDING;
141 }
142
143 int UnixDomainServerSocket::DoAccept(scoped_ptr<StreamSocket>* socket) {
144 int new_socket = HANDLE_EINTR(accept(socket_fd_, NULL, NULL));
145 if (new_socket < 0) {
146 // Treat as IO_PENDING for ECONNABORTED. See MapAcceptError() in
147 // tcp_socket_libevent.cc for detailed reason.
148 return errno == ECONNABORTED ? ERR_IO_PENDING : MapSystemError(errno);
149 }
150
151 uid_t user_id;
152 gid_t group_id;
153 if (!GetPeerIds(new_socket, &user_id, &group_id) ||
154 !auth_callback_.Run(user_id, group_id)) {
155 close(new_socket);
156 return ERR_IO_PENDING;
157 }
158
159 if (SetNonBlocking(new_socket)) {
160 close(new_socket);
161 return ERR_IO_PENDING;
162 }
163
164 socket->reset(new UnixDomainClientSocket(new_socket));
165 return OK;
166 }
167
168 void UnixDomainServerSocket::DidCompleteAccept() {
169 int rv = DoAccept(accept_socket_);
170 if (rv == ERR_IO_PENDING)
171 return;
172
173 accept_socket_watcher_.StopWatchingFileDescriptor();
174 accept_socket_ = NULL;
175 base::ResetAndReturn(&accept_callback_).Run(rv);
176 }
177
178 void UnixDomainServerSocket::OnFileCanReadWithoutBlocking(int fd) {
179 if (accept_callback_.is_null()) {
180 NOTREACHED();
181 } else {
182 DidCompleteAccept();
183 }
184 }
185
186 void UnixDomainServerSocket::OnFileCanWriteWithoutBlocking(int fd) {
187 NOTREACHED();
188 }
189
190 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698