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 #pragma once 17 18 #include <android-base/unique_fd.h> 19 #include <binder/IBinder.h> 20 #include <binder/RpcSession.h> 21 #include <binder/RpcThreads.h> 22 #include <binder/RpcTransport.h> 23 #include <utils/Errors.h> 24 #include <utils/RefBase.h> 25 26 #include <mutex> 27 #include <thread> 28 29 namespace android { 30 31 class FdTrigger; 32 class RpcServerTrusty; 33 class RpcSocketAddress; 34 35 /** 36 * This represents a server of an interface, which may be connected to by any 37 * number of clients over sockets. 38 * 39 * Usage: 40 * auto server = RpcServer::make(); 41 * // only supports one now 42 * if (!server->setup*Server(...)) { 43 * :( 44 * } 45 * server->join(); 46 */ 47 class RpcServer final : public virtual RefBase, private RpcSession::EventListener { 48 public: 49 static sp<RpcServer> make( 50 std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr); 51 52 /** 53 * Creates an RPC server that bootstraps sessions using an existing 54 * Unix domain socket pair. 55 * 56 * Callers should create a pair of SOCK_STREAM Unix domain sockets, pass 57 * one to RpcServer::setupUnixDomainSocketBootstrapServer and the other 58 * to RpcSession::setupUnixDomainSocketBootstrapClient. Multiple client 59 * session can be created from the client end of the pair. 60 */ 61 [[nodiscard]] status_t setupUnixDomainSocketBootstrapServer(base::unique_fd serverFd); 62 63 /** 64 * This represents a session for responses, e.g.: 65 * 66 * process A serves binder a 67 * process B opens a session to process A 68 * process B makes binder b and sends it to A 69 * A uses this 'back session' to send things back to B 70 */ 71 [[nodiscard]] status_t setupUnixDomainServer(const char* path); 72 73 /** 74 * Sets up an RPC server with a raw socket file descriptor. 75 * The socket should be created and bound to a socket address already, e.g. 76 * the socket can be created in init.rc. 77 * 78 * This method is used in the libbinder_rpc_unstable API 79 * RunInitUnixDomainRpcServer(). 80 */ 81 [[nodiscard]] status_t setupRawSocketServer(base::unique_fd socket_fd); 82 83 /** 84 * Creates an RPC server binding to the given CID at the given port. 85 */ 86 [[nodiscard]] status_t setupVsockServer(unsigned int bindCid, unsigned int port); 87 88 /** 89 * Creates an RPC server at the current port using IPv4. 90 * 91 * TODO(b/182914638): IPv6 support 92 * 93 * Set |port| to 0 to pick an ephemeral port; see discussion of 94 * /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort| 95 * will be set to the picked port number, if it is not null. 96 * 97 * Set the IPv4 address for the socket to be listening on. 98 * "127.0.0.1" allows for local connections from the same device. 99 * "0.0.0.0" allows for connections on any IP address that the device may 100 * have 101 */ 102 [[nodiscard]] status_t setupInetServer(const char* address, unsigned int port, 103 unsigned int* assignedPort = nullptr); 104 105 /** 106 * If setup*Server has been successful, return true. Otherwise return false. 107 */ 108 [[nodiscard]] bool hasServer(); 109 110 /** 111 * If hasServer(), return the server FD. Otherwise return invalid FD. 112 */ 113 [[nodiscard]] base::unique_fd releaseServer(); 114 115 /** 116 * Set up server using an external FD previously set up by releaseServer(). 117 * Return false if there's already a server. 118 */ 119 [[nodiscard]] status_t setupExternalServer(base::unique_fd serverFd); 120 121 /** 122 * This must be called before adding a client session. This corresponds 123 * to the number of incoming connections to RpcSession objects in the 124 * server, which will correspond to the number of outgoing connections 125 * in client RpcSession objects. 126 * 127 * If this is not specified, this will be a single-threaded server. 128 * 129 * TODO(b/167966510): these are currently created per client, but these 130 * should be shared. 131 */ 132 void setMaxThreads(size_t threads); 133 size_t getMaxThreads(); 134 135 /** 136 * By default, the latest protocol version which is supported by a client is 137 * used. However, this can be used in order to prevent newer protocol 138 * versions from ever being used. This is expected to be useful for testing. 139 */ 140 void setProtocolVersion(uint32_t version); 141 142 /** 143 * Set the supported transports for sending and receiving file descriptors. 144 * 145 * Clients will propose a mode when connecting. If the mode is not in the 146 * provided list, the connection will be rejected. 147 */ 148 void setSupportedFileDescriptorTransportModes( 149 const std::vector<RpcSession::FileDescriptorTransportMode>& modes); 150 151 /** 152 * The root object can be retrieved by any client, without any 153 * authentication. TODO(b/183988761) 154 * 155 * Holds a strong reference to the root object. 156 */ 157 void setRootObject(const sp<IBinder>& binder); 158 /** 159 * Holds a weak reference to the root object. 160 */ 161 void setRootObjectWeak(const wp<IBinder>& binder); 162 /** 163 * Allows a root object to be created for each session. 164 * 165 * Takes one argument: a callable that is invoked once per new session. 166 * The callable takes two arguments: a type-erased pointer to an OS- and 167 * transport-specific address structure, e.g., sockaddr_vm for vsock, and 168 * an integer representing the size in bytes of that structure. The 169 * callable should validate the size, then cast the type-erased pointer 170 * to a pointer to the actual type of the address, e.g., const void* to 171 * const sockaddr_vm*. 172 */ 173 void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object); 174 sp<IBinder> getRootObject(); 175 176 /** 177 * Set optional filter of incoming connections based on the peer's address. 178 * 179 * Takes one argument: a callable that is invoked on each accept()-ed 180 * connection and returns false if the connection should be dropped. 181 * See the description of setPerSessionRootObject() for details about 182 * the callable's arguments. 183 */ 184 void setConnectionFilter(std::function<bool(const void*, size_t)>&& filter); 185 186 /** 187 * See RpcTransportCtx::getCertificate 188 */ 189 std::vector<uint8_t> getCertificate(RpcCertificateFormat); 190 191 /** 192 * Runs join() in a background thread. Immediately returns. 193 */ 194 void start(); 195 196 /** 197 * You must have at least one client session before calling this. 198 * 199 * If a client needs to actively terminate join, call shutdown() in a separate thread. 200 * 201 * At any given point, there can only be one thread calling join(). 202 * 203 * Warning: if shutdown is called, this will return while the shutdown is 204 * still occurring. To ensure that the service is fully shutdown, you might 205 * want to call shutdown after 'join' returns. 206 */ 207 void join(); 208 209 /** 210 * Shut down any existing join(). Return true if successfully shut down, false otherwise 211 * (e.g. no join() is running). Will wait for the server to be fully 212 * shutdown. 213 * 214 * Warning: this will hang if it is called from its own thread. 215 */ 216 [[nodiscard]] bool shutdown(); 217 218 /** 219 * For debugging! 220 */ 221 std::vector<sp<RpcSession>> listSessions(); 222 size_t numUninitializedSessions(); 223 224 /** 225 * Whether any requests are currently being processed. 226 */ 227 bool hasActiveRequests(); 228 229 ~RpcServer(); 230 231 private: 232 friend RpcServerTrusty; 233 friend sp<RpcServer>; 234 explicit RpcServer(std::unique_ptr<RpcTransportCtx> ctx); 235 236 void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override; 237 void onSessionIncomingThreadEnded() override; 238 239 status_t setupExternalServer( 240 base::unique_fd serverFd, 241 std::function<status_t(const RpcServer&, RpcTransportFd*)>&& acceptFn); 242 243 static constexpr size_t kRpcAddressSize = 128; 244 static void establishConnection( 245 sp<RpcServer>&& server, RpcTransportFd clientFd, 246 std::array<uint8_t, kRpcAddressSize> addr, size_t addrLen, 247 std::function<void(sp<RpcSession>&&, RpcSession::PreJoinSetupResult&&)>&& joinFn); 248 static status_t acceptSocketConnection(const RpcServer& server, RpcTransportFd* out); 249 static status_t recvmsgSocketConnection(const RpcServer& server, RpcTransportFd* out); 250 251 [[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address); 252 253 const std::unique_ptr<RpcTransportCtx> mCtx; 254 size_t mMaxThreads = 1; 255 std::optional<uint32_t> mProtocolVersion; 256 // A mode is supported if the N'th bit is on, where N is the mode enum's value. 257 std::bitset<8> mSupportedFileDescriptorTransportModes = std::bitset<8>().set( 258 static_cast<size_t>(RpcSession::FileDescriptorTransportMode::NONE)); 259 RpcTransportFd mServer; // socket we are accepting sessions on 260 261 RpcMutex mLock; // for below 262 std::unique_ptr<RpcMaybeThread> mJoinThread; 263 bool mJoinThreadRunning = false; 264 std::map<RpcMaybeThread::id, RpcMaybeThread> mConnectingThreads; 265 266 sp<IBinder> mRootObject; 267 wp<IBinder> mRootObjectWeak; 268 std::function<sp<IBinder>(const void*, size_t)> mRootObjectFactory; 269 std::function<bool(const void*, size_t)> mConnectionFilter; 270 std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions; 271 std::unique_ptr<FdTrigger> mShutdownTrigger; 272 RpcConditionVariable mShutdownCv; 273 std::function<status_t(const RpcServer& server, RpcTransportFd* out)> mAcceptFn; 274 }; 275 276 } // namespace android 277