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

Side by Side Diff: mojo/shell/domain_socket/unix_domain_server_socket_posix.cc

Issue 775343004: Move //mojo/shell to //shell (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years 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 "mojo/shell/domain_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/logging.h"
13 #include "mojo/shell/domain_socket/completion_callback.h"
14 #include "mojo/shell/domain_socket/net_errors.h"
15 #include "mojo/shell/domain_socket/socket_descriptor.h"
16 #include "mojo/shell/domain_socket/socket_libevent.h"
17 #include "mojo/shell/domain_socket/unix_domain_client_socket_posix.h"
18
19 namespace mojo {
20 namespace shell {
21
22 namespace {
23
24 // Intended for use as SetterCallbacks in Accept() helper methods.
25 void SetSocketDescriptor(SocketDescriptor* socket,
26 scoped_ptr<SocketLibevent> accepted_socket) {
27 *socket = accepted_socket->ReleaseConnectedSocket();
28 }
29
30 } // anonymous namespace
31
32 UnixDomainServerSocket::UnixDomainServerSocket(
33 const AuthCallback& auth_callback,
34 bool use_abstract_namespace)
35 : auth_callback_(auth_callback),
36 use_abstract_namespace_(use_abstract_namespace) {
37 DCHECK(!auth_callback_.is_null());
38 }
39
40 UnixDomainServerSocket::~UnixDomainServerSocket() {
41 }
42
43 // static
44 bool UnixDomainServerSocket::GetPeerCredentials(SocketDescriptor socket,
45 Credentials* credentials) {
46 struct ucred user_cred;
47 socklen_t len = sizeof(user_cred);
48 if (getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &user_cred, &len) < 0)
49 return false;
50 credentials->process_id = user_cred.pid;
51 credentials->user_id = user_cred.uid;
52 credentials->group_id = user_cred.gid;
53 return true;
54 }
55
56 int UnixDomainServerSocket::ListenWithPath(const std::string& unix_domain_path,
57 int backlog) {
58 DCHECK(!listen_socket_);
59
60 SockaddrStorage address;
61 if (!UnixDomainClientSocket::FillAddress(
62 unix_domain_path, use_abstract_namespace_, &address)) {
63 return net::ERR_ADDRESS_INVALID;
64 }
65
66 scoped_ptr<SocketLibevent> socket(new SocketLibevent);
67 int rv = socket->Open(AF_UNIX);
68 DCHECK_NE(net::ERR_IO_PENDING, rv);
69 if (rv != net::OK)
70 return rv;
71
72 rv = socket->Bind(address);
73 DCHECK_NE(net::ERR_IO_PENDING, rv);
74 if (rv != net::OK) {
75 PLOG(ERROR) << "Could not bind unix domain socket to " << unix_domain_path
76 << (use_abstract_namespace_ ? " (with abstract namespace)"
77 : "");
78 return rv;
79 }
80
81 rv = socket->Listen(backlog);
82 DCHECK_NE(net::ERR_IO_PENDING, rv);
83 if (rv != net::OK)
84 return rv;
85
86 listen_socket_.swap(socket);
87 return rv;
88 }
89
90 int UnixDomainServerSocket::Accept(SocketDescriptor* socket,
91 const CompletionCallback& callback) {
92 DCHECK(socket);
93
94 SetterCallback setter_callback = base::Bind(&SetSocketDescriptor, socket);
95 return DoAccept(setter_callback, callback);
96 }
97
98 int UnixDomainServerSocket::DoAccept(const SetterCallback& setter_callback,
99 const CompletionCallback& callback) {
100 DCHECK(!setter_callback.is_null());
101 DCHECK(!callback.is_null());
102 DCHECK(listen_socket_);
103 DCHECK(!accept_socket_);
104
105 while (true) {
106 int rv = listen_socket_->Accept(
107 &accept_socket_,
108 base::Bind(&UnixDomainServerSocket::AcceptCompleted,
109 base::Unretained(this),
110 setter_callback,
111 callback));
112 if (rv != net::OK)
113 return rv;
114 if (AuthenticateAndGetStreamSocket(setter_callback))
115 return net::OK;
116 // Accept another socket because authentication error should be transparent
117 // to the caller.
118 }
119 }
120
121 void UnixDomainServerSocket::AcceptCompleted(
122 const SetterCallback& setter_callback,
123 const CompletionCallback& callback,
124 int rv) {
125 if (rv != net::OK) {
126 callback.Run(rv);
127 return;
128 }
129
130 if (AuthenticateAndGetStreamSocket(setter_callback)) {
131 callback.Run(net::OK);
132 return;
133 }
134
135 // Accept another socket because authentication error should be transparent
136 // to the caller.
137 rv = DoAccept(setter_callback, callback);
138 if (rv != net::ERR_IO_PENDING)
139 callback.Run(rv);
140 }
141
142 bool UnixDomainServerSocket::AuthenticateAndGetStreamSocket(
143 const SetterCallback& setter_callback) {
144 DCHECK(accept_socket_);
145
146 Credentials credentials;
147 if (!GetPeerCredentials(accept_socket_->socket_fd(), &credentials) ||
148 !auth_callback_.Run(credentials)) {
149 accept_socket_.reset();
150 return false;
151 }
152
153 setter_callback.Run(accept_socket_.Pass());
154 return true;
155 }
156
157 } // namespace shell
158 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698