| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 1 | /* | 
 | 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 |  | 
 | 19 | #include <sys/socket.h> | 
 | 20 | #include <sys/un.h> | 
 | 21 |  | 
| Steven Moreland | f137de9 | 2021-04-24 01:54:26 +0000 | [diff] [blame] | 22 | #include <thread> | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 23 | #include <vector> | 
 | 24 |  | 
| Steven Moreland | 5802c2b | 2021-05-12 20:13:04 +0000 | [diff] [blame] | 25 | #include <android-base/scopeguard.h> | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 26 | #include <binder/Parcel.h> | 
 | 27 | #include <binder/RpcServer.h> | 
 | 28 | #include <log/log.h> | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 29 |  | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 30 | #include "RpcSocketAddress.h" | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 31 | #include "RpcState.h" | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 32 | #include "RpcWireFormat.h" | 
 | 33 |  | 
 | 34 | namespace android { | 
 | 35 |  | 
| Steven Moreland | 5802c2b | 2021-05-12 20:13:04 +0000 | [diff] [blame] | 36 | using base::ScopeGuard; | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 37 | using base::unique_fd; | 
 | 38 |  | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 39 | RpcServer::RpcServer() {} | 
| Yifan Hong | 436f0e6 | 2021-05-19 15:25:34 -0700 | [diff] [blame] | 40 | RpcServer::~RpcServer() { | 
 | 41 |     (void)shutdown(); | 
 | 42 | } | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 43 |  | 
 | 44 | sp<RpcServer> RpcServer::make() { | 
| Steven Moreland | 1a3a8ef | 2021-04-02 02:52:46 +0000 | [diff] [blame] | 45 |     return sp<RpcServer>::make(); | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 46 | } | 
 | 47 |  | 
 | 48 | void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() { | 
 | 49 |     mAgreedExperimental = true; | 
 | 50 | } | 
 | 51 |  | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 52 | bool RpcServer::setupUnixDomainServer(const char* path) { | 
 | 53 |     return setupSocketServer(UnixSocketAddress(path)); | 
 | 54 | } | 
 | 55 |  | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 56 | bool RpcServer::setupVsockServer(unsigned int port) { | 
 | 57 |     // realizing value w/ this type at compile time to avoid ubsan abort | 
 | 58 |     constexpr unsigned int kAnyCid = VMADDR_CID_ANY; | 
 | 59 |  | 
 | 60 |     return setupSocketServer(VsockSocketAddress(kAnyCid, port)); | 
 | 61 | } | 
 | 62 |  | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 63 | bool RpcServer::setupInetServer(unsigned int port, unsigned int* assignedPort) { | 
 | 64 |     const char* kAddr = "127.0.0.1"; | 
 | 65 |  | 
 | 66 |     if (assignedPort != nullptr) *assignedPort = 0; | 
 | 67 |     auto aiStart = InetSocketAddress::getAddrInfo(kAddr, port); | 
 | 68 |     if (aiStart == nullptr) return false; | 
 | 69 |     for (auto ai = aiStart.get(); ai != nullptr; ai = ai->ai_next) { | 
 | 70 |         InetSocketAddress socketAddress(ai->ai_addr, ai->ai_addrlen, kAddr, port); | 
 | 71 |         if (!setupSocketServer(socketAddress)) { | 
 | 72 |             continue; | 
 | 73 |         } | 
 | 74 |  | 
 | 75 |         LOG_ALWAYS_FATAL_IF(socketAddress.addr()->sa_family != AF_INET, "expecting inet"); | 
 | 76 |         sockaddr_in addr{}; | 
 | 77 |         socklen_t len = sizeof(addr); | 
 | 78 |         if (0 != getsockname(mServer.get(), reinterpret_cast<sockaddr*>(&addr), &len)) { | 
 | 79 |             int savedErrno = errno; | 
 | 80 |             ALOGE("Could not getsockname at %s: %s", socketAddress.toString().c_str(), | 
 | 81 |                   strerror(savedErrno)); | 
 | 82 |             return false; | 
 | 83 |         } | 
 | 84 |         LOG_ALWAYS_FATAL_IF(len != sizeof(addr), "Wrong socket type: len %zu vs len %zu", | 
 | 85 |                             static_cast<size_t>(len), sizeof(addr)); | 
 | 86 |         unsigned int realPort = ntohs(addr.sin_port); | 
 | 87 |         LOG_ALWAYS_FATAL_IF(port != 0 && realPort != port, | 
 | 88 |                             "Requesting inet server on %s but it is set up on %u.", | 
 | 89 |                             socketAddress.toString().c_str(), realPort); | 
 | 90 |  | 
 | 91 |         if (assignedPort != nullptr) { | 
 | 92 |             *assignedPort = realPort; | 
 | 93 |         } | 
 | 94 |  | 
 | 95 |         return true; | 
 | 96 |     } | 
 | 97 |     ALOGE("None of the socket address resolved for %s:%u can be set up as inet server.", kAddr, | 
 | 98 |           port); | 
 | 99 |     return false; | 
 | 100 | } | 
 | 101 |  | 
| Steven Moreland | f137de9 | 2021-04-24 01:54:26 +0000 | [diff] [blame] | 102 | void RpcServer::setMaxThreads(size_t threads) { | 
 | 103 |     LOG_ALWAYS_FATAL_IF(threads <= 0, "RpcServer is useless without threads"); | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 104 |     LOG_ALWAYS_FATAL_IF(mJoinThreadRunning, "Cannot set max threads while running"); | 
| Steven Moreland | f137de9 | 2021-04-24 01:54:26 +0000 | [diff] [blame] | 105 |     mMaxThreads = threads; | 
 | 106 | } | 
 | 107 |  | 
 | 108 | size_t RpcServer::getMaxThreads() { | 
 | 109 |     return mMaxThreads; | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 110 | } | 
 | 111 |  | 
 | 112 | void RpcServer::setRootObject(const sp<IBinder>& binder) { | 
| Steven Moreland | ebafe33 | 2021-04-24 00:24:35 +0000 | [diff] [blame] | 113 |     std::lock_guard<std::mutex> _l(mLock); | 
| Yifan Hong | 4ffb0c7 | 2021-05-07 18:35:14 -0700 | [diff] [blame] | 114 |     mRootObjectWeak = mRootObject = binder; | 
 | 115 | } | 
 | 116 |  | 
 | 117 | void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) { | 
 | 118 |     std::lock_guard<std::mutex> _l(mLock); | 
 | 119 |     mRootObject.clear(); | 
 | 120 |     mRootObjectWeak = binder; | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 121 | } | 
 | 122 |  | 
 | 123 | sp<IBinder> RpcServer::getRootObject() { | 
| Steven Moreland | ebafe33 | 2021-04-24 00:24:35 +0000 | [diff] [blame] | 124 |     std::lock_guard<std::mutex> _l(mLock); | 
| Yifan Hong | 4ffb0c7 | 2021-05-07 18:35:14 -0700 | [diff] [blame] | 125 |     bool hasWeak = mRootObjectWeak.unsafe_get(); | 
 | 126 |     sp<IBinder> ret = mRootObjectWeak.promote(); | 
 | 127 |     ALOGW_IF(hasWeak && ret == nullptr, "RpcServer root object is freed, returning nullptr"); | 
 | 128 |     return ret; | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 129 | } | 
 | 130 |  | 
| Yifan Hong | 326afd1 | 2021-05-19 15:24:54 -0700 | [diff] [blame] | 131 | static void joinRpcServer(sp<RpcServer>&& thiz) { | 
 | 132 |     thiz->join(); | 
 | 133 | } | 
 | 134 |  | 
 | 135 | void RpcServer::start() { | 
 | 136 |     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); | 
 | 137 |     std::lock_guard<std::mutex> _l(mLock); | 
 | 138 |     LOG_ALWAYS_FATAL_IF(mJoinThread.get(), "Already started!"); | 
 | 139 |     mJoinThread = std::make_unique<std::thread>(&joinRpcServer, sp<RpcServer>::fromExisting(this)); | 
 | 140 | } | 
 | 141 |  | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 142 | void RpcServer::join() { | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 143 |     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); | 
 | 144 |  | 
 | 145 |     { | 
 | 146 |         std::lock_guard<std::mutex> _l(mLock); | 
 | 147 |         LOG_ALWAYS_FATAL_IF(!mServer.ok(), "RpcServer must be setup to join."); | 
 | 148 |         LOG_ALWAYS_FATAL_IF(mShutdownTrigger != nullptr, "Already joined"); | 
 | 149 |         mJoinThreadRunning = true; | 
| Steven Moreland | e47511f | 2021-05-20 00:07:41 +0000 | [diff] [blame] | 150 |         mShutdownTrigger = RpcSession::FdTrigger::make(); | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 151 |         LOG_ALWAYS_FATAL_IF(mShutdownTrigger == nullptr, "Cannot create join signaler"); | 
| Steven Moreland | d539fbf | 2021-05-05 23:40:25 +0000 | [diff] [blame] | 152 |     } | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 153 |  | 
| Steven Moreland | 2b4f380 | 2021-05-22 01:46:27 +0000 | [diff] [blame] | 154 |     status_t status; | 
 | 155 |     while ((status = mShutdownTrigger->triggerablePollRead(mServer)) == OK) { | 
| Steven Moreland | 410325a | 2021-06-02 18:37:42 +0000 | [diff] [blame] | 156 |         unique_fd clientFd(TEMP_FAILURE_RETRY( | 
 | 157 |                 accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC))); | 
 | 158 |  | 
 | 159 |         if (clientFd < 0) { | 
 | 160 |             ALOGE("Could not accept4 socket: %s", strerror(errno)); | 
 | 161 |             continue; | 
 | 162 |         } | 
 | 163 |         LOG_RPC_DETAIL("accept4 on fd %d yields fd %d", mServer.get(), clientFd.get()); | 
 | 164 |  | 
 | 165 |         { | 
 | 166 |             std::lock_guard<std::mutex> _l(mLock); | 
 | 167 |             std::thread thread = | 
 | 168 |                     std::thread(&RpcServer::establishConnection, sp<RpcServer>::fromExisting(this), | 
 | 169 |                                 std::move(clientFd)); | 
 | 170 |             mConnectingThreads[thread.get_id()] = std::move(thread); | 
 | 171 |         } | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 172 |     } | 
| Steven Moreland | 2b4f380 | 2021-05-22 01:46:27 +0000 | [diff] [blame] | 173 |     LOG_RPC_DETAIL("RpcServer::join exiting with %s", statusToString(status).c_str()); | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 174 |  | 
 | 175 |     { | 
 | 176 |         std::lock_guard<std::mutex> _l(mLock); | 
 | 177 |         mJoinThreadRunning = false; | 
 | 178 |     } | 
 | 179 |     mShutdownCv.notify_all(); | 
| Steven Moreland | d539fbf | 2021-05-05 23:40:25 +0000 | [diff] [blame] | 180 | } | 
 | 181 |  | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 182 | bool RpcServer::shutdown() { | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 183 |     std::unique_lock<std::mutex> _l(mLock); | 
| Steven Moreland | 9d11b92 | 2021-05-20 01:22:58 +0000 | [diff] [blame] | 184 |     if (mShutdownTrigger == nullptr) { | 
 | 185 |         LOG_RPC_DETAIL("Cannot shutdown. No shutdown trigger installed."); | 
 | 186 |         return false; | 
 | 187 |     } | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 188 |  | 
 | 189 |     mShutdownTrigger->trigger(); | 
| Steven Moreland | a8b4429 | 2021-06-08 01:27:53 +0000 | [diff] [blame] | 190 |     for (auto& [id, session] : mSessions) { | 
 | 191 |         (void)id; | 
 | 192 |         session->mShutdownTrigger->trigger(); | 
 | 193 |     } | 
 | 194 |  | 
| Steven Moreland | ee3f466 | 2021-05-22 01:07:33 +0000 | [diff] [blame] | 195 |     while (mJoinThreadRunning || !mConnectingThreads.empty() || !mSessions.empty()) { | 
| Steven Moreland | af4ca71 | 2021-05-24 23:22:08 +0000 | [diff] [blame] | 196 |         if (std::cv_status::timeout == mShutdownCv.wait_for(_l, std::chrono::seconds(1))) { | 
 | 197 |             ALOGE("Waiting for RpcServer to shut down (1s w/o progress). Join thread running: %d, " | 
 | 198 |                   "Connecting threads: " | 
 | 199 |                   "%zu, Sessions: %zu. Is your server deadlocked?", | 
 | 200 |                   mJoinThreadRunning, mConnectingThreads.size(), mSessions.size()); | 
 | 201 |         } | 
| Steven Moreland | 9d11b92 | 2021-05-20 01:22:58 +0000 | [diff] [blame] | 202 |     } | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 203 |  | 
| Yifan Hong | 326afd1 | 2021-05-19 15:24:54 -0700 | [diff] [blame] | 204 |     // At this point, we know join() is about to exit, but the thread that calls | 
 | 205 |     // join() may not have exited yet. | 
 | 206 |     // If RpcServer owns the join thread (aka start() is called), make sure the thread exits; | 
 | 207 |     // otherwise ~thread() may call std::terminate(), which may crash the process. | 
 | 208 |     // If RpcServer does not own the join thread (aka join() is called directly), | 
 | 209 |     // then the owner of RpcServer is responsible for cleaning up that thread. | 
 | 210 |     if (mJoinThread.get()) { | 
 | 211 |         mJoinThread->join(); | 
 | 212 |         mJoinThread.reset(); | 
 | 213 |     } | 
 | 214 |  | 
| Yifan Hong | 1a23585 | 2021-05-13 16:07:47 -0700 | [diff] [blame] | 215 |     mShutdownTrigger = nullptr; | 
 | 216 |     return true; | 
 | 217 | } | 
 | 218 |  | 
| Steven Moreland | bdb53ab | 2021-05-05 17:57:41 +0000 | [diff] [blame] | 219 | std::vector<sp<RpcSession>> RpcServer::listSessions() { | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 220 |     std::lock_guard<std::mutex> _l(mLock); | 
| Steven Moreland | bdb53ab | 2021-05-05 17:57:41 +0000 | [diff] [blame] | 221 |     std::vector<sp<RpcSession>> sessions; | 
 | 222 |     for (auto& [id, session] : mSessions) { | 
| Steven Moreland | 736664b | 2021-05-01 04:27:25 +0000 | [diff] [blame] | 223 |         (void)id; | 
| Steven Moreland | bdb53ab | 2021-05-05 17:57:41 +0000 | [diff] [blame] | 224 |         sessions.push_back(session); | 
| Steven Moreland | 736664b | 2021-05-01 04:27:25 +0000 | [diff] [blame] | 225 |     } | 
| Steven Moreland | bdb53ab | 2021-05-05 17:57:41 +0000 | [diff] [blame] | 226 |     return sessions; | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 227 | } | 
 | 228 |  | 
| Steven Moreland | d539fbf | 2021-05-05 23:40:25 +0000 | [diff] [blame] | 229 | size_t RpcServer::numUninitializedSessions() { | 
 | 230 |     std::lock_guard<std::mutex> _l(mLock); | 
 | 231 |     return mConnectingThreads.size(); | 
 | 232 | } | 
 | 233 |  | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 234 | void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd) { | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 235 |     // TODO(b/183988761): cannot trust this simple ID | 
| Yifan Hong | b300550 | 2021-05-19 15:37:00 -0700 | [diff] [blame] | 236 |     LOG_ALWAYS_FATAL_IF(!server->mAgreedExperimental, "no!"); | 
| Steven Moreland | 9d11b92 | 2021-05-20 01:22:58 +0000 | [diff] [blame] | 237 |  | 
 | 238 |     // mShutdownTrigger can only be cleared once connection threads have joined. | 
 | 239 |     // It must be set before this thread is started | 
 | 240 |     LOG_ALWAYS_FATAL_IF(server->mShutdownTrigger == nullptr); | 
 | 241 |  | 
| Steven Moreland | 659416d | 2021-05-11 00:47:50 +0000 | [diff] [blame] | 242 |     RpcConnectionHeader header; | 
 | 243 |     status_t status = server->mShutdownTrigger->interruptableReadFully(clientFd.get(), &header, | 
 | 244 |                                                                        sizeof(header)); | 
| Steven Moreland | 2b4f380 | 2021-05-22 01:46:27 +0000 | [diff] [blame] | 245 |     bool idValid = status == OK; | 
| Steven Moreland | 9d11b92 | 2021-05-20 01:22:58 +0000 | [diff] [blame] | 246 |     if (!idValid) { | 
| Steven Moreland | 2b4f380 | 2021-05-22 01:46:27 +0000 | [diff] [blame] | 247 |         ALOGE("Failed to read ID for client connecting to RPC server: %s", | 
 | 248 |               statusToString(status).c_str()); | 
 | 249 |         // still need to cleanup before we can return | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 250 |     } | 
| Steven Moreland | 659416d | 2021-05-11 00:47:50 +0000 | [diff] [blame] | 251 |     bool reverse = header.options & RPC_CONNECTION_OPTION_REVERSE; | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 252 |  | 
 | 253 |     std::thread thisThread; | 
 | 254 |     sp<RpcSession> session; | 
 | 255 |     { | 
| Steven Moreland | 9d11b92 | 2021-05-20 01:22:58 +0000 | [diff] [blame] | 256 |         std::unique_lock<std::mutex> _l(server->mLock); | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 257 |  | 
| Yifan Hong | b300550 | 2021-05-19 15:37:00 -0700 | [diff] [blame] | 258 |         auto threadId = server->mConnectingThreads.find(std::this_thread::get_id()); | 
 | 259 |         LOG_ALWAYS_FATAL_IF(threadId == server->mConnectingThreads.end(), | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 260 |                             "Must establish connection on owned thread"); | 
 | 261 |         thisThread = std::move(threadId->second); | 
| Steven Moreland | adc5dca | 2021-05-25 02:06:03 +0000 | [diff] [blame] | 262 |         ScopeGuard detachGuard = [&]() { | 
 | 263 |             thisThread.detach(); | 
| Steven Moreland | 9d11b92 | 2021-05-20 01:22:58 +0000 | [diff] [blame] | 264 |             _l.unlock(); | 
 | 265 |             server->mShutdownCv.notify_all(); | 
 | 266 |         }; | 
| Steven Moreland | adc5dca | 2021-05-25 02:06:03 +0000 | [diff] [blame] | 267 |         server->mConnectingThreads.erase(threadId); | 
| Steven Moreland | 9d11b92 | 2021-05-20 01:22:58 +0000 | [diff] [blame] | 268 |  | 
| Steven Moreland | a8b4429 | 2021-06-08 01:27:53 +0000 | [diff] [blame] | 269 |         if (!idValid || server->mShutdownTrigger->isTriggered()) { | 
| Steven Moreland | 5802c2b | 2021-05-12 20:13:04 +0000 | [diff] [blame] | 270 |             return; | 
 | 271 |         } | 
 | 272 |  | 
| Steven Moreland | 01a6bad | 2021-06-11 00:59:20 +0000 | [diff] [blame] | 273 |         RpcAddress sessionId = RpcAddress::fromRawEmbedded(&header.sessionId); | 
 | 274 |  | 
 | 275 |         if (sessionId.isZero()) { | 
| Steven Moreland | 659416d | 2021-05-11 00:47:50 +0000 | [diff] [blame] | 276 |             if (reverse) { | 
 | 277 |                 ALOGE("Cannot create a new session with a reverse connection, would leak"); | 
 | 278 |                 return; | 
 | 279 |             } | 
 | 280 |  | 
| Yifan Hong | 6fe1963 | 2021-06-24 15:50:12 -0700 | [diff] [blame] | 281 |             sessionId = RpcAddress::zero(); | 
| Steven Moreland | 01a6bad | 2021-06-11 00:59:20 +0000 | [diff] [blame] | 282 |             size_t tries = 0; | 
 | 283 |             do { | 
 | 284 |                 // don't block if there is some entropy issue | 
 | 285 |                 if (tries++ > 5) { | 
 | 286 |                     ALOGE("Cannot find new address: %s", sessionId.toString().c_str()); | 
 | 287 |                     return; | 
 | 288 |                 } | 
 | 289 |  | 
 | 290 |                 sessionId = RpcAddress::random(true /*forServer*/); | 
 | 291 |             } while (server->mSessions.end() != server->mSessions.find(sessionId)); | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 292 |  | 
 | 293 |             session = RpcSession::make(); | 
| Steven Moreland | 103424e | 2021-06-02 18:16:19 +0000 | [diff] [blame] | 294 |             session->setMaxThreads(server->mMaxThreads); | 
| Steven Moreland | a8b4429 | 2021-06-08 01:27:53 +0000 | [diff] [blame] | 295 |             if (!session->setForServer(server, | 
 | 296 |                                        sp<RpcServer::EventListener>::fromExisting( | 
 | 297 |                                                static_cast<RpcServer::EventListener*>( | 
 | 298 |                                                        server.get())), | 
| Steven Moreland | 01a6bad | 2021-06-11 00:59:20 +0000 | [diff] [blame] | 299 |                                        sessionId)) { | 
| Steven Moreland | a8b4429 | 2021-06-08 01:27:53 +0000 | [diff] [blame] | 300 |                 ALOGE("Failed to attach server to session"); | 
 | 301 |                 return; | 
 | 302 |             } | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 303 |  | 
| Steven Moreland | 01a6bad | 2021-06-11 00:59:20 +0000 | [diff] [blame] | 304 |             server->mSessions[sessionId] = session; | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 305 |         } else { | 
| Steven Moreland | 01a6bad | 2021-06-11 00:59:20 +0000 | [diff] [blame] | 306 |             auto it = server->mSessions.find(sessionId); | 
| Yifan Hong | b300550 | 2021-05-19 15:37:00 -0700 | [diff] [blame] | 307 |             if (it == server->mSessions.end()) { | 
| Steven Moreland | 01a6bad | 2021-06-11 00:59:20 +0000 | [diff] [blame] | 308 |                 ALOGE("Cannot add thread, no record of session with ID %s", | 
 | 309 |                       sessionId.toString().c_str()); | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 310 |                 return; | 
 | 311 |             } | 
 | 312 |             session = it->second; | 
 | 313 |         } | 
| Steven Moreland | 5802c2b | 2021-05-12 20:13:04 +0000 | [diff] [blame] | 314 |  | 
| Steven Moreland | 659416d | 2021-05-11 00:47:50 +0000 | [diff] [blame] | 315 |         if (reverse) { | 
| Steven Moreland | b86e26b | 2021-06-12 00:35:58 +0000 | [diff] [blame] | 316 |             LOG_ALWAYS_FATAL_IF(!session->addOutgoingConnection(std::move(clientFd), true), | 
| Steven Moreland | 659416d | 2021-05-11 00:47:50 +0000 | [diff] [blame] | 317 |                                 "server state must already be initialized"); | 
 | 318 |             return; | 
 | 319 |         } | 
 | 320 |  | 
| Steven Moreland | 5802c2b | 2021-05-12 20:13:04 +0000 | [diff] [blame] | 321 |         detachGuard.Disable(); | 
| Steven Moreland | c88b7fc | 2021-06-10 00:40:39 +0000 | [diff] [blame] | 322 |         session->preJoinThreadOwnership(std::move(thisThread)); | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 323 |     } | 
 | 324 |  | 
| Steven Moreland | c88b7fc | 2021-06-10 00:40:39 +0000 | [diff] [blame] | 325 |     auto setupResult = session->preJoinSetup(std::move(clientFd)); | 
 | 326 |  | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 327 |     // avoid strong cycle | 
 | 328 |     server = nullptr; | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 329 |  | 
| Steven Moreland | c88b7fc | 2021-06-10 00:40:39 +0000 | [diff] [blame] | 330 |     RpcSession::join(std::move(session), std::move(setupResult)); | 
| Steven Moreland | a63ff93 | 2021-05-12 00:03:15 +0000 | [diff] [blame] | 331 | } | 
 | 332 |  | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 333 | bool RpcServer::setupSocketServer(const RpcSocketAddress& addr) { | 
| Steven Moreland | 704fc1a | 2021-05-04 23:13:14 +0000 | [diff] [blame] | 334 |     LOG_RPC_DETAIL("Setting up socket server %s", addr.toString().c_str()); | 
| Yifan Hong | 0eb5a67 | 2021-05-12 18:00:25 -0700 | [diff] [blame] | 335 |     LOG_ALWAYS_FATAL_IF(hasServer(), "Each RpcServer can only have one server."); | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 336 |  | 
 | 337 |     unique_fd serverFd( | 
 | 338 |             TEMP_FAILURE_RETRY(socket(addr.addr()->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0))); | 
 | 339 |     if (serverFd == -1) { | 
 | 340 |         ALOGE("Could not create socket: %s", strerror(errno)); | 
 | 341 |         return false; | 
 | 342 |     } | 
 | 343 |  | 
 | 344 |     if (0 != TEMP_FAILURE_RETRY(bind(serverFd.get(), addr.addr(), addr.addrSize()))) { | 
 | 345 |         int savedErrno = errno; | 
 | 346 |         ALOGE("Could not bind socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); | 
 | 347 |         return false; | 
 | 348 |     } | 
 | 349 |  | 
 | 350 |     if (0 != TEMP_FAILURE_RETRY(listen(serverFd.get(), 1 /*backlog*/))) { | 
 | 351 |         int savedErrno = errno; | 
 | 352 |         ALOGE("Could not listen socket at %s: %s", addr.toString().c_str(), strerror(savedErrno)); | 
 | 353 |         return false; | 
 | 354 |     } | 
 | 355 |  | 
| Steven Moreland | 704fc1a | 2021-05-04 23:13:14 +0000 | [diff] [blame] | 356 |     LOG_RPC_DETAIL("Successfully setup socket server %s", addr.toString().c_str()); | 
 | 357 |  | 
| Yifan Hong | c276f8d | 2021-05-13 17:13:44 -0700 | [diff] [blame] | 358 |     if (!setupExternalServer(std::move(serverFd))) { | 
 | 359 |         ALOGE("Another thread has set up server while calling setupSocketServer. Race?"); | 
 | 360 |         return false; | 
 | 361 |     } | 
| Steven Moreland | 611d15f | 2021-05-01 01:28:27 +0000 | [diff] [blame] | 362 |     return true; | 
 | 363 | } | 
 | 364 |  | 
| Steven Moreland | 19fc9f7 | 2021-06-10 03:57:30 +0000 | [diff] [blame] | 365 | void RpcServer::onSessionLockedAllIncomingThreadsEnded(const sp<RpcSession>& session) { | 
| Steven Moreland | ee78e76 | 2021-05-05 21:12:51 +0000 | [diff] [blame] | 366 |     auto id = session->mId; | 
 | 367 |     LOG_ALWAYS_FATAL_IF(id == std::nullopt, "Server sessions must be initialized with ID"); | 
| Steven Moreland | 01a6bad | 2021-06-11 00:59:20 +0000 | [diff] [blame] | 368 |     LOG_RPC_DETAIL("Dropping session with address %s", id->toString().c_str()); | 
| Steven Moreland | ee78e76 | 2021-05-05 21:12:51 +0000 | [diff] [blame] | 369 |  | 
 | 370 |     std::lock_guard<std::mutex> _l(mLock); | 
 | 371 |     auto it = mSessions.find(*id); | 
| Steven Moreland | 01a6bad | 2021-06-11 00:59:20 +0000 | [diff] [blame] | 372 |     LOG_ALWAYS_FATAL_IF(it == mSessions.end(), "Bad state, unknown session id %s", | 
 | 373 |                         id->toString().c_str()); | 
 | 374 |     LOG_ALWAYS_FATAL_IF(it->second != session, "Bad state, session has id mismatch %s", | 
 | 375 |                         id->toString().c_str()); | 
| Steven Moreland | ee78e76 | 2021-05-05 21:12:51 +0000 | [diff] [blame] | 376 |     (void)mSessions.erase(it); | 
 | 377 | } | 
 | 378 |  | 
| Steven Moreland | 19fc9f7 | 2021-06-10 03:57:30 +0000 | [diff] [blame] | 379 | void RpcServer::onSessionIncomingThreadEnded() { | 
| Steven Moreland | ee3f466 | 2021-05-22 01:07:33 +0000 | [diff] [blame] | 380 |     mShutdownCv.notify_all(); | 
 | 381 | } | 
 | 382 |  | 
| Yifan Hong | 0eb5a67 | 2021-05-12 18:00:25 -0700 | [diff] [blame] | 383 | bool RpcServer::hasServer() { | 
| Yifan Hong | 00aeb76 | 2021-05-12 17:07:36 -0700 | [diff] [blame] | 384 |     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); | 
| Yifan Hong | 0eb5a67 | 2021-05-12 18:00:25 -0700 | [diff] [blame] | 385 |     std::lock_guard<std::mutex> _l(mLock); | 
 | 386 |     return mServer.ok(); | 
 | 387 | } | 
 | 388 |  | 
| Yifan Hong | 00aeb76 | 2021-05-12 17:07:36 -0700 | [diff] [blame] | 389 | unique_fd RpcServer::releaseServer() { | 
 | 390 |     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); | 
 | 391 |     std::lock_guard<std::mutex> _l(mLock); | 
 | 392 |     return std::move(mServer); | 
 | 393 | } | 
 | 394 |  | 
 | 395 | bool RpcServer::setupExternalServer(base::unique_fd serverFd) { | 
 | 396 |     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!"); | 
 | 397 |     std::lock_guard<std::mutex> _l(mLock); | 
 | 398 |     if (mServer.ok()) { | 
 | 399 |         ALOGE("Each RpcServer can only have one server."); | 
 | 400 |         return false; | 
 | 401 |     } | 
 | 402 |     mServer = std::move(serverFd); | 
 | 403 |     return true; | 
 | 404 | } | 
 | 405 |  | 
| Steven Moreland | 5553ac4 | 2020-11-11 02:14:45 +0000 | [diff] [blame] | 406 | } // namespace android |