blob: 63d4dde9645408354c0fe504b8859fe2fc4bfe08 [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 "RpcServer"
18
Yifan Hong1a235852021-05-13 16:07:47 -070019#include <poll.h>
Steven Moreland5553ac42020-11-11 02:14:45 +000020#include <sys/socket.h>
21#include <sys/un.h>
22
Steven Morelandf137de92021-04-24 01:54:26 +000023#include <thread>
Steven Moreland5553ac42020-11-11 02:14:45 +000024#include <vector>
25
Yifan Hong1a235852021-05-13 16:07:47 -070026#include <android-base/macros.h>
Steven Moreland5802c2b2021-05-12 20:13:04 +000027#include <android-base/scopeguard.h>
Steven Moreland5553ac42020-11-11 02:14:45 +000028#include <binder/Parcel.h>
29#include <binder/RpcServer.h>
30#include <log/log.h>
Steven Moreland5553ac42020-11-11 02:14:45 +000031
Steven Moreland611d15f2021-05-01 01:28:27 +000032#include "RpcSocketAddress.h"
Yifan Hong1a235852021-05-13 16:07:47 -070033#include "RpcState.h"
Steven Moreland5553ac42020-11-11 02:14:45 +000034#include "RpcWireFormat.h"
35
36namespace android {
37
Steven Moreland5802c2b2021-05-12 20:13:04 +000038using base::ScopeGuard;
Steven Moreland611d15f2021-05-01 01:28:27 +000039using base::unique_fd;
40
Steven Moreland5553ac42020-11-11 02:14:45 +000041RpcServer::RpcServer() {}
Yifan Hong436f0e62021-05-19 15:25:34 -070042RpcServer::~RpcServer() {
43 (void)shutdown();
44}
Steven Moreland5553ac42020-11-11 02:14:45 +000045
46sp<RpcServer> RpcServer::make() {
Steven Moreland1a3a8ef2021-04-02 02:52:46 +000047 return sp<RpcServer>::make();
Steven Moreland5553ac42020-11-11 02:14:45 +000048}
49
50void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() {
51 mAgreedExperimental = true;
52}
53
Steven Moreland611d15f2021-05-01 01:28:27 +000054bool RpcServer::setupUnixDomainServer(const char* path) {
55 return setupSocketServer(UnixSocketAddress(path));
56}
57
Steven Moreland611d15f2021-05-01 01:28:27 +000058bool RpcServer::setupVsockServer(unsigned int port) {
59 // realizing value w/ this type at compile time to avoid ubsan abort
60 constexpr unsigned int kAnyCid = VMADDR_CID_ANY;
61
62 return setupSocketServer(VsockSocketAddress(kAnyCid, port));
63}
64
Steven Moreland611d15f2021-05-01 01:28:27 +000065bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) {
66 const char* kAddr = "127.0.0.1";
67
68 if (assignedPort != nullptr) *assignedPort = 0;
69 auto aiStart = InetSocketAddress::getAddrInfo(kAddr, port);
70 if (aiStart == nullptr) return false;
71 for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) {
72 InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, kAddr, port);
73 if (!setupSocketServer(socketAddress)) {
74 continue;
75 }
76
77 LOG_ALWAYS_FATAL_IF(socketAddress.addr()->sa_family != AF_INET, "expecting inet");
78 sockaddr_in addr{};
79 socklen_t len = sizeof(addr);
80 if (0 != getsockname(mServer.get(), reinterpret_cast<sockaddr*>(&addr), &len)) {
81 int savedErrno = errno;
82 ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(),
83 strerror(savedErrno));
84 return false;
85 }
86 LOG_ALWAYS_FATAL_IF(len != sizeof(addr), "Wrong socket type: len %zu vs len %zu",
87 static_cast<size_t>(len), sizeof(addr));
88 unsigned int realPort = ntohs(addr.sin_port);
89 LOG_ALWAYS_FATAL_IF(port != 0 && realPort != port,
90 "Requesting inet server on %s but it is set up on %u.",
91 socketAddress.toString().c_str(), realPort);
92
93 if (assignedPort != nullptr) {
94 *assignedPort = realPort;
95 }
96
97 return true;
98 }
99 ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr,
100 port);
101 return false;
102}
103
Steven Morelandf137de92021-04-24 01:54:26 +0000104void RpcServer::setMaxThreads(size_t threads) {
105 LOG_ALWAYS_FATAL_IF(threads <= 0, "RpcServer is useless without threads");
Yifan Hong1a235852021-05-13 16:07:47 -0700106 LOG_ALWAYS_FATAL_IF(mJoinThreadRunning, "Cannot set max threads while running");
Steven Morelandf137de92021-04-24 01:54:26 +0000107 mMaxThreads = threads;
108}
109
110size_t RpcServer::getMaxThreads() {
111 return mMaxThreads;
Steven Moreland5553ac42020-11-11 02:14:45 +0000112}
113
114void RpcServer::setRootObject(const sp<IBinder>& binder) {
Steven Morelandebafe332021-04-24 00:24:35 +0000115 std::lock_guard<std::mutex> _l(mLock);
Yifan Hong4ffb0c72021-05-07 18:35:14 -0700116 mRootObjectWeak = mRootObject = binder;
117}
118
119void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) {
120 std::lock_guard<std::mutex> _l(mLock);
121 mRootObject.clear();
122 mRootObjectWeak = binder;
Steven Moreland5553ac42020-11-11 02:14:45 +0000123}
124
125sp<IBinder> RpcServer::getRootObject() {
Steven Morelandebafe332021-04-24 00:24:35 +0000126 std::lock_guard<std::mutex> _l(mLock);
Yifan Hong4ffb0c72021-05-07 18:35:14 -0700127 bool hasWeak = mRootObjectWeak.unsafe_get();
128 sp<IBinder> ret = mRootObjectWeak.promote();
129 ALOGW_IF(hasWeak && ret == nullptr, "RpcServer root object is freed, returning nullptr");
130 return ret;
Steven Moreland5553ac42020-11-11 02:14:45 +0000131}
132
Yifan Hong1a235852021-05-13 16:07:47 -0700133std::unique_ptr<RpcServer::FdTrigger> RpcServer::FdTrigger::make() {
134 auto ret = std::make_unique<RpcServer::FdTrigger>();
135 if (!android::base::Pipe(&ret->mRead, &ret->mWrite)) return nullptr;
136 return ret;
137}
138
139void RpcServer::FdTrigger::trigger() {
140 mWrite.reset();
141}
142
Steven Moreland611d15f2021-05-01 01:28:27 +0000143void RpcServer::join() {
Yifan Hong1a235852021-05-13 16:07:47 -0700144 LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
145
146 {
147 std::lock_guard<std::mutex> _l(mLock);
148 LOG_ALWAYS_FATAL_IF(!mServer.ok(), "RpcServer must be setup to join.");
149 LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined");
150 mJoinThreadRunning = true;
151 mShutdownTrigger = FdTrigger::make();
152 LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr, "Cannot create join signaler");
Steven Morelandd539fbf2021-05-05 23:40:25 +0000153 }
Yifan Hong1a235852021-05-13 16:07:47 -0700154
155 while (true) {
156 pollfd pfd[]{{.fd = mServer.get(), .events = POLLIN, .revents = 0},
157 {.fd = mShutdownTrigger->readFd().get(), .events = POLLHUP, .revents = 0}};
158 int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
159 if (ret < 0) {
160 ALOGE("Could not poll socket: %s", strerror(errno));
161 continue;
162 }
163 if (ret == 0) {
164 continue;
165 }
166 if (pfd[1].revents & POLLHUP) {
167 LOG_RPC_DETAIL("join() exiting because shutdown requested.");
168 break;
169 }
170
171 (void)acceptOneNoCheck();
172 }
173
174 {
175 std::lock_guard<std::mutex> _l(mLock);
176 mJoinThreadRunning = false;
177 }
178 mShutdownCv.notify_all();
Steven Morelandd539fbf2021-05-05 23:40:25 +0000179}
180
181bool RpcServer::acceptOne() {
Steven Morelandf137de92021-04-24 01:54:26 +0000182 LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
Yifan Hong1a235852021-05-13 16:07:47 -0700183 LOG_ALWAYS_FATAL_IF(!hasServer(), "RpcServer must be setup to acceptOne.");
184 return acceptOneNoCheck();
185}
Steven Morelandd539fbf2021-05-05 23:40:25 +0000186
Yifan Hong1a235852021-05-13 16:07:47 -0700187bool RpcServer::acceptOneNoCheck() {
Steven Morelandd539fbf2021-05-05 23:40:25 +0000188 unique_fd clientFd(
189 TEMP_FAILURE_RETRY(accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC)));
190
191 if (clientFd < 0) {
192 ALOGE("Could not accept4 socket: %s", strerror(errno));
193 return false;
194 }
195 LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get());
196
Steven Morelandf137de92021-04-24 01:54:26 +0000197 {
198 std::lock_guard<std::mutex> _l(mLock);
Steven Morelandd539fbf2021-05-05 23:40:25 +0000199 std::thread thread =
200 std::thread(&RpcServer::establishConnection, this,
201 std::move(sp<RpcServer>::fromExisting(this)), std::move(clientFd));
202 mConnectingThreads[thread.get_id()] = std::move(thread);
Steven Morelandf137de92021-04-24 01:54:26 +0000203 }
204
Steven Morelandd539fbf2021-05-05 23:40:25 +0000205 return true;
Steven Morelandf137de92021-04-24 01:54:26 +0000206}
207
Yifan Hong1a235852021-05-13 16:07:47 -0700208bool RpcServer::shutdown() {
Yifan Hong1a235852021-05-13 16:07:47 -0700209 std::unique_lock<std::mutex> _l(mLock);
210 if (mShutdownTrigger == nullptr) return false;
211
212 mShutdownTrigger->trigger();
213 while (mJoinThreadRunning) mShutdownCv.wait(_l);
214
215 mShutdownTrigger = nullptr;
216 return true;
217}
218
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000219std::vector<sp<RpcSession>> RpcServer::listSessions() {
Steven Moreland611d15f2021-05-01 01:28:27 +0000220 std::lock_guard<std::mutex> _l(mLock);
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000221 std::vector<sp<RpcSession>> sessions;
222 for (auto& [id, session] : mSessions) {
Steven Moreland736664b2021-05-01 04:27:25 +0000223 (void)id;
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000224 sessions.push_back(session);
Steven Moreland736664b2021-05-01 04:27:25 +0000225 }
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000226 return sessions;
Steven Moreland611d15f2021-05-01 01:28:27 +0000227}
228
Steven Morelandd539fbf2021-05-05 23:40:25 +0000229size_t RpcServer::numUninitializedSessions() {
230 std::lock_guard<std::mutex> _l(mLock);
231 return mConnectingThreads.size();
232}
233
Steven Morelanda63ff932021-05-12 00:03:15 +0000234void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd) {
235 LOG_ALWAYS_FATAL_IF(this != server.get(), "Must pass same ownership object");
236
237 // TODO(b/183988761): cannot trust this simple ID
238 LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
Steven Moreland5802c2b2021-05-12 20:13:04 +0000239 bool idValid = true;
Steven Morelanda63ff932021-05-12 00:03:15 +0000240 int32_t id;
241 if (sizeof(id) != read(clientFd.get(), &id, sizeof(id))) {
242 ALOGE("Could not read ID from fd %d", clientFd.get());
Steven Moreland5802c2b2021-05-12 20:13:04 +0000243 idValid = false;
Steven Morelanda63ff932021-05-12 00:03:15 +0000244 }
245
246 std::thread thisThread;
247 sp<RpcSession> session;
248 {
249 std::lock_guard<std::mutex> _l(mLock);
250
251 auto threadId = mConnectingThreads.find(std::this_thread::get_id());
252 LOG_ALWAYS_FATAL_IF(threadId == mConnectingThreads.end(),
253 "Must establish connection on owned thread");
254 thisThread = std::move(threadId->second);
Steven Moreland5802c2b2021-05-12 20:13:04 +0000255 ScopeGuard detachGuard = [&]() { thisThread.detach(); };
Steven Morelanda63ff932021-05-12 00:03:15 +0000256 mConnectingThreads.erase(threadId);
257
Steven Moreland5802c2b2021-05-12 20:13:04 +0000258 if (!idValid) {
259 return;
260 }
261
Steven Morelanda63ff932021-05-12 00:03:15 +0000262 if (id == RPC_SESSION_ID_NEW) {
263 LOG_ALWAYS_FATAL_IF(mSessionIdCounter >= INT32_MAX, "Out of session IDs");
264 mSessionIdCounter++;
265
266 session = RpcSession::make();
267 session->setForServer(wp<RpcServer>::fromExisting(this), mSessionIdCounter);
268
269 mSessions[mSessionIdCounter] = session;
270 } else {
271 auto it = mSessions.find(id);
272 if (it == mSessions.end()) {
273 ALOGE("Cannot add thread, no record of session with ID %d", id);
274 return;
275 }
276 session = it->second;
277 }
Steven Moreland5802c2b2021-05-12 20:13:04 +0000278
279 detachGuard.Disable();
280 session->preJoin(std::move(thisThread));
Steven Morelanda63ff932021-05-12 00:03:15 +0000281 }
282
283 // avoid strong cycle
284 server = nullptr;
285 //
286 //
287 // DO NOT ACCESS MEMBER VARIABLES BELOW
288 //
289
Steven Moreland5802c2b2021-05-12 20:13:04 +0000290 session->join(std::move(clientFd));
Steven Morelanda63ff932021-05-12 00:03:15 +0000291}
292
Steven Moreland611d15f2021-05-01 01:28:27 +0000293bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) {
Steven Moreland704fc1a2021-05-04 23:13:14 +0000294 LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str());
Yifan Hong0eb5a672021-05-12 18:00:25 -0700295 LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server.");
Steven Moreland611d15f2021-05-01 01:28:27 +0000296
297 unique_fd serverFd(
298 TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0)));
299 if (serverFd == -1) {
300 ALOGE("Could not create socket: %s", strerror(errno));
301 return false;
302 }
303
304 if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) {
305 int savedErrno = errno;
306 ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
307 return false;
308 }
309
310 if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) {
311 int savedErrno = errno;
312 ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno));
313 return false;
314 }
315
Steven Moreland704fc1a2021-05-04 23:13:14 +0000316 LOG_RPC_DETAIL("Successfully setup socket server %s", addr.toString().c_str());
317
Yifan Hongc276f8d2021-05-13 17:13:44 -0700318 if (!setupExternalServer(std::move(serverFd))) {
319 ALOGE("Another thread has set up server while calling setupSocketServer. Race?");
320 return false;
321 }
Steven Moreland611d15f2021-05-01 01:28:27 +0000322 return true;
323}
324
Steven Morelandee78e762021-05-05 21:12:51 +0000325void RpcServer::onSessionTerminating(const sp<RpcSession>& session) {
326 auto id = session->mId;
327 LOG_ALWAYS_FATAL_IF(id == std::nullopt, "Server sessions must be initialized with ID");
328 LOG_RPC_DETAIL("Dropping session %d", *id);
329
330 std::lock_guard<std::mutex> _l(mLock);
331 auto it = mSessions.find(*id);
332 LOG_ALWAYS_FATAL_IF(it == mSessions.end(), "Bad state, unknown session id %d", *id);
333 LOG_ALWAYS_FATAL_IF(it->second != session, "Bad state, session has id mismatch %d", *id);
334 (void)mSessions.erase(it);
335}
336
Yifan Hong0eb5a672021-05-12 18:00:25 -0700337bool RpcServer::hasServer() {
Yifan Hong00aeb762021-05-12 17:07:36 -0700338 LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
Yifan Hong0eb5a672021-05-12 18:00:25 -0700339 std::lock_guard<std::mutex> _l(mLock);
340 return mServer.ok();
341}
342
Yifan Hong00aeb762021-05-12 17:07:36 -0700343unique_fd RpcServer::releaseServer() {
344 LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
345 std::lock_guard<std::mutex> _l(mLock);
346 return std::move(mServer);
347}
348
349bool RpcServer::setupExternalServer(base::unique_fd serverFd) {
350 LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
351 std::lock_guard<std::mutex> _l(mLock);
352 if (mServer.ok()) {
353 ALOGE("Each RpcServer can only have one server.");
354 return false;
355 }
356 mServer = std::move(serverFd);
357 return true;
358}
359
Steven Moreland5553ac42020-11-11 02:14:45 +0000360} // namespace android