• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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