blob: dab3246fc5a5b6fada0c5d9d2f5d310d42f98f10 [file] [log] [blame]
Steven Moreland5553ac42020-11-11 02:14:45 +00001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "RpcConnection"
18
19#include <binder/RpcConnection.h>
20
21#include <binder/Parcel.h>
22#include <binder/Stability.h>
Steven Moreland53583542021-03-30 00:25:41 +000023#include <utils/String8.h>
Steven Moreland5553ac42020-11-11 02:14:45 +000024
25#include "RpcState.h"
26#include "RpcWireFormat.h"
27
28#include <sys/socket.h>
29#include <sys/types.h>
30#include <sys/un.h>
31#include <unistd.h>
32
Steven Moreland53583542021-03-30 00:25:41 +000033#ifdef __GLIBC__
Steven Moreland5553ac42020-11-11 02:14:45 +000034extern "C" pid_t gettid();
35#endif
36
Steven Moreland53583542021-03-30 00:25:41 +000037#ifdef __BIONIC__
38#include <linux/vm_sockets.h>
39#endif
40
Steven Moreland5553ac42020-11-11 02:14:45 +000041namespace android {
42
43using base::unique_fd;
44
Steven Moreland53583542021-03-30 00:25:41 +000045RpcConnection::SocketAddress::~SocketAddress() {}
46
Steven Moreland5553ac42020-11-11 02:14:45 +000047RpcConnection::RpcConnection() {
48 LOG_RPC_DETAIL("RpcConnection created %p", this);
49
50 mState = std::make_unique<RpcState>();
51}
52RpcConnection::~RpcConnection() {
53 LOG_RPC_DETAIL("RpcConnection destroyed %p", this);
54}
55
56sp<RpcConnection> RpcConnection::make() {
57 return new RpcConnection;
58}
59
Steven Moreland53583542021-03-30 00:25:41 +000060class UnixSocketAddress : public RpcConnection::SocketAddress {
61public:
62 explicit UnixSocketAddress(const char* path) : mAddr({.sun_family = AF_UNIX}) {
63 unsigned int pathLen = strlen(path) + 1;
64 LOG_ALWAYS_FATAL_IF(pathLen > sizeof(mAddr.sun_path), "%u %s", pathLen, path);
65 memcpy(mAddr.sun_path, path, pathLen);
66 }
67 virtual ~UnixSocketAddress() {}
68 std::string toString() const override {
69 return String8::format("path '%.*s'", static_cast<int>(sizeof(mAddr.sun_path)),
70 mAddr.sun_path)
71 .c_str();
72 }
73 const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
74 size_t addrSize() const override { return sizeof(mAddr); }
75
76private:
77 sockaddr_un mAddr;
78};
79
Steven Moreland5553ac42020-11-11 02:14:45 +000080bool RpcConnection::setupUnixDomainServer(const char* path) {
Steven Moreland53583542021-03-30 00:25:41 +000081 return addServer(UnixSocketAddress(path));
Steven Moreland5553ac42020-11-11 02:14:45 +000082}
83
84bool RpcConnection::addUnixDomainClient(const char* path) {
Steven Moreland53583542021-03-30 00:25:41 +000085 return addClient(UnixSocketAddress(path));
Steven Moreland5553ac42020-11-11 02:14:45 +000086}
87
Steven Moreland53583542021-03-30 00:25:41 +000088#ifdef __BIONIC__
89
90class VsockSocketAddress : public RpcConnection::SocketAddress {
91public:
92 VsockSocketAddress(unsigned int cid, unsigned int port)
93 : mAddr({
94 .svm_family = AF_VSOCK,
95 .svm_port = port,
96 .svm_cid = cid,
97 }) {}
98 virtual ~VsockSocketAddress() {}
99 std::string toString() const override {
100 return String8::format("cid %du port %du", mAddr.svm_cid, mAddr.svm_port).c_str();
101 }
102 const sockaddr* addr() const override { return reinterpret_cast<const sockaddr*>(&mAddr); }
103 size_t addrSize() const override { return sizeof(mAddr); }
104
105private:
106 sockaddr_vm mAddr;
107};
108
109bool RpcConnection::setupVsockServer(unsigned int port) {
110 // realizing value w/ this type at compile time to avoid ubsan abort
111 constexpr unsigned int kAnyCid = VMADDR_CID_ANY;
112
113 return addServer(VsockSocketAddress(kAnyCid, port));
114}
115
116bool RpcConnection::addVsockClient(unsigned int cid, unsigned int port) {
117 return addClient(VsockSocketAddress(cid, port));
118}
119
120#endif // __BIONIC__
121
Steven Moreland5553ac42020-11-11 02:14:45 +0000122sp<IBinder> RpcConnection::getRootObject() {
123 ExclusiveSocket socket(this, SocketUse::CLIENT);
124 return state()->getRootObject(socket.fd(), this);
125}
126
127status_t RpcConnection::transact(const RpcAddress& address, uint32_t code, const Parcel& data,
128 Parcel* reply, uint32_t flags) {
129 ExclusiveSocket socket(this,
130 (flags & IBinder::FLAG_ONEWAY) ? SocketUse::CLIENT_ASYNC
131 : SocketUse::CLIENT);
132 return state()->transact(socket.fd(), address, code, data, this, reply, flags);
133}
134
135status_t RpcConnection::sendDecStrong(const RpcAddress& address) {
136 ExclusiveSocket socket(this, SocketUse::CLIENT_REFCOUNT);
137 return state()->sendDecStrong(socket.fd(), address);
138}
139
140void RpcConnection::join() {
141 // establish a connection
142 {
Steven Moreland53583542021-03-30 00:25:41 +0000143 unique_fd clientFd(
144 TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, 0 /*length*/, SOCK_CLOEXEC)));
Steven Moreland5553ac42020-11-11 02:14:45 +0000145 if (clientFd < 0) {
146 // If this log becomes confusing, should save more state from setupUnixDomainServer
147 // in order to output here.
148 ALOGE("Could not accept4 socket: %s", strerror(errno));
149 return;
150 }
151
152 LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
153
Steven Moreland53583542021-03-30 00:25:41 +0000154 assignServerToThisThread(std::move(clientFd));
Steven Moreland5553ac42020-11-11 02:14:45 +0000155 }
156
157 // We may not use the connection we just established (two threads might
158 // establish connections for each other), but for now, just use one
159 // server/socket connection.
160 ExclusiveSocket socket(this, SocketUse::SERVER);
161
162 while (true) {
163 status_t error = state()->getAndExecuteCommand(socket.fd(), this);
164
165 if (error != OK) {
166 ALOGI("Binder socket thread closing w/ status %s", statusToString(error).c_str());
167 return;
168 }
169 }
170}
171
172void RpcConnection::setForServer(const wp<RpcServer>& server) {
173 mForServer = server;
174}
175
176wp<RpcServer> RpcConnection::server() {
177 return mForServer;
178}
179
Steven Moreland53583542021-03-30 00:25:41 +0000180bool RpcConnection::addServer(const SocketAddress& addr) {
181 LOG_ALWAYS_FATAL_IF(mServer.get() != -1, "Each RpcConnection can only have one server.");
182
183 unique_fd serverFd(
184 TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
185 if (serverFd == -1) {
186 ALOGE("Could not create socket: %s", strerror(errno));
187 return false;
188 }
189
190 if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) {
191 int savedErrno = errno;
192 ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
193 return false;
194 }
195
196 if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) {
197 int savedErrno = errno;
198 ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
199 return false;
200 }
201
202 mServer = std::move(serverFd);
203 return true;
Steven Moreland5553ac42020-11-11 02:14:45 +0000204}
205
Steven Moreland53583542021-03-30 00:25:41 +0000206bool RpcConnection::addClient(const SocketAddress& addr) {
207 unique_fd serverFd(
208 TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
209 if (serverFd == -1) {
210 int savedErrno = errno;
211 ALOGE("Could not create socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
212 return false;
213 }
214
215 if (0 != TEMP_FAILURE_RETRY(connect(serverFd.get(), addr.addr(), addr.addrSize()))) {
216 int savedErrno = errno;
217 ALOGE("Could not connect socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
218 return false;
219 }
220
221 LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
222
223 std::lock_guard<std::mutex> _l(mSocketMutex);
224 sp<ConnectionSocket> connection = new ConnectionSocket();
225 connection->fd = std::move(serverFd);
226 mClients.push_back(connection);
227 return true;
228}
229
230void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) {
Steven Moreland5553ac42020-11-11 02:14:45 +0000231 std::lock_guard<std::mutex> _l(mSocketMutex);
232 sp<ConnectionSocket> connection = new ConnectionSocket();
233 connection->fd = std::move(fd);
234 mServers.push_back(connection);
235}
236
237RpcConnection::ExclusiveSocket::ExclusiveSocket(const sp<RpcConnection>& connection, SocketUse use)
238 : mConnection(connection) {
239 pid_t tid = gettid();
240 std::unique_lock<std::mutex> _l(mConnection->mSocketMutex);
241
242 mConnection->mWaitingThreads++;
243 while (true) {
244 sp<ConnectionSocket> exclusive;
245 sp<ConnectionSocket> available;
246
247 // CHECK FOR DEDICATED CLIENT SOCKET
248 //
249 // A server/looper should always use a dedicated connection.
250 if (use != SocketUse::SERVER) {
251 findSocket(tid, &exclusive, &available, mConnection->mClients,
252 mConnection->mClientsOffset);
253
254 // WARNING: this assumes a server cannot request its client to send
255 // a transaction, as mServers is excluded below.
256 //
257 // Imagine we have more than one thread in play, and a single thread
258 // sends a synchronous, then an asynchronous command. Imagine the
259 // asynchronous command is sent on the first client socket. Then, if
260 // we naively send a synchronous command to that same socket, the
261 // thread on the far side might be busy processing the asynchronous
262 // command. So, we move to considering the second available thread
263 // for subsequent calls.
264 if (use == SocketUse::CLIENT_ASYNC && (exclusive != nullptr || available != nullptr)) {
265 mConnection->mClientsOffset =
266 (mConnection->mClientsOffset + 1) % mConnection->mClients.size();
267 }
268 }
269
270 // USE SERVING SOCKET (to start serving or for nested transaction)
271 //
272 // asynchronous calls cannot be nested
273 if (use != SocketUse::CLIENT_ASYNC) {
274 // servers should start serving on an available thread only
275 // otherwise, this should only be a nested call
276 bool useAvailable = use == SocketUse::SERVER;
277
278 findSocket(tid, &exclusive, (useAvailable ? &available : nullptr),
279 mConnection->mServers, 0 /* index hint */);
280 }
281
282 // if our thread is already using a connection, prioritize using that
283 if (exclusive != nullptr) {
284 mSocket = exclusive;
285 mReentrant = true;
286 break;
287 } else if (available != nullptr) {
288 mSocket = available;
289 mSocket->exclusiveTid = tid;
290 break;
291 }
292
293 LOG_ALWAYS_FATAL_IF(use == SocketUse::SERVER, "Must create connection to join one.");
294
295 // in regular binder, this would usually be a deadlock :)
296 LOG_ALWAYS_FATAL_IF(mConnection->mClients.size() == 0,
297 "Not a client of any connection. You must create a connection to an "
298 "RPC server to make any non-nested (e.g. oneway or on another thread) "
299 "calls.");
300
301 LOG_RPC_DETAIL("No available connection (have %zu clients and %zu servers). Waiting...",
302 mConnection->mClients.size(), mConnection->mServers.size());
303 mConnection->mSocketCv.wait(_l);
304 }
305 mConnection->mWaitingThreads--;
306}
307
308void RpcConnection::ExclusiveSocket::findSocket(pid_t tid, sp<ConnectionSocket>* exclusive,
309 sp<ConnectionSocket>* available,
310 std::vector<sp<ConnectionSocket>>& sockets,
311 size_t socketsIndexHint) {
312 LOG_ALWAYS_FATAL_IF(sockets.size() > 0 && socketsIndexHint >= sockets.size(),
313 "Bad index %zu >= %zu", socketsIndexHint, sockets.size());
314
315 if (*exclusive != nullptr) return; // consistent with break below
316
317 for (size_t i = 0; i < sockets.size(); i++) {
318 sp<ConnectionSocket>& socket = sockets[(i + socketsIndexHint) % sockets.size()];
319
320 // take first available connection (intuition = caching)
321 if (available && *available == nullptr && socket->exclusiveTid == std::nullopt) {
322 *available = socket;
323 continue;
324 }
325
326 // though, prefer to take connection which is already inuse by this thread
327 // (nested transactions)
328 if (exclusive && socket->exclusiveTid == tid) {
329 *exclusive = socket;
330 break; // consistent with return above
331 }
332 }
333}
334
335RpcConnection::ExclusiveSocket::~ExclusiveSocket() {
336 // reentrant use of a connection means something less deep in the call stack
337 // is using this fd, and it retains the right to it. So, we don't give up
338 // exclusive ownership, and no thread is freed.
339 if (!mReentrant) {
340 std::unique_lock<std::mutex> _l(mConnection->mSocketMutex);
341 mSocket->exclusiveTid = std::nullopt;
342 if (mConnection->mWaitingThreads > 0) {
343 _l.unlock();
344 mConnection->mSocketCv.notify_one();
345 }
346 }
347}
348
349} // namespace android