• 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/RpcTransport.h>
22 #include <utils/Errors.h>
23 #include <utils/RefBase.h>
24 
25 #include <mutex>
26 #include <thread>
27 
28 namespace android {
29 
30 class FdTrigger;
31 class RpcSocketAddress;
32 
33 /**
34  * This represents a server of an interface, which may be connected to by any
35  * number of clients over sockets.
36  *
37  * Usage:
38  *     auto server = RpcServer::make();
39  *     // only supports one now
40  *     if (!server->setup*Server(...)) {
41  *         :(
42  *     }
43  *     server->join();
44  */
45 class RpcServer final : public virtual RefBase, private RpcSession::EventListener {
46 public:
47     static sp<RpcServer> make(
48             std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr);
49 
50     /**
51      * This represents a session for responses, e.g.:
52      *
53      *     process A serves binder a
54      *     process B opens a session to process A
55      *     process B makes binder b and sends it to A
56      *     A uses this 'back session' to send things back to B
57      */
58     [[nodiscard]] status_t setupUnixDomainServer(const char* path);
59 
60     /**
61      * Creates an RPC server at the current port.
62      */
63     [[nodiscard]] status_t setupVsockServer(unsigned int port);
64 
65     /**
66      * Creates an RPC server at the current port using IPv4.
67      *
68      * TODO(b/182914638): IPv6 support
69      *
70      * Set |port| to 0 to pick an ephemeral port; see discussion of
71      * /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort|
72      * will be set to the picked port number, if it is not null.
73      *
74      * Set the IPv4 address for the socket to be listening on.
75      * "127.0.0.1" allows for local connections from the same device.
76      * "0.0.0.0" allows for connections on any IP address that the device may
77      * have
78      */
79     [[nodiscard]] status_t setupInetServer(const char* address, unsigned int port,
80                                            unsigned int* assignedPort = nullptr);
81 
82     /**
83      * If setup*Server has been successful, return true. Otherwise return false.
84      */
85     [[nodiscard]] bool hasServer();
86 
87     /**
88      * If hasServer(), return the server FD. Otherwise return invalid FD.
89      */
90     [[nodiscard]] base::unique_fd releaseServer();
91 
92     /**
93      * Set up server using an external FD previously set up by releaseServer().
94      * Return false if there's already a server.
95      */
96     [[nodiscard]] status_t setupExternalServer(base::unique_fd serverFd);
97 
98     /**
99      * This must be called before adding a client session.
100      *
101      * If this is not specified, this will be a single-threaded server.
102      *
103      * TODO(b/167966510): these are currently created per client, but these
104      * should be shared.
105      */
106     void setMaxThreads(size_t threads);
107     size_t getMaxThreads();
108 
109     /**
110      * By default, the latest protocol version which is supported by a client is
111      * used. However, this can be used in order to prevent newer protocol
112      * versions from ever being used. This is expected to be useful for testing.
113      */
114     void setProtocolVersion(uint32_t version);
115 
116     /**
117      * The root object can be retrieved by any client, without any
118      * authentication. TODO(b/183988761)
119      *
120      * Holds a strong reference to the root object.
121      */
122     void setRootObject(const sp<IBinder>& binder);
123     /**
124      * Holds a weak reference to the root object.
125      */
126     void setRootObjectWeak(const wp<IBinder>& binder);
127     /**
128      * Allows a root object to be created for each session
129      */
130     void setPerSessionRootObject(std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& object);
131     sp<IBinder> getRootObject();
132 
133     /**
134      * See RpcTransportCtx::getCertificate
135      */
136     std::vector<uint8_t> getCertificate(RpcCertificateFormat);
137 
138     /**
139      * Runs join() in a background thread. Immediately returns.
140      */
141     void start();
142 
143     /**
144      * You must have at least one client session before calling this.
145      *
146      * If a client needs to actively terminate join, call shutdown() in a separate thread.
147      *
148      * At any given point, there can only be one thread calling join().
149      *
150      * Warning: if shutdown is called, this will return while the shutdown is
151      * still occurring. To ensure that the service is fully shutdown, you might
152      * want to call shutdown after 'join' returns.
153      */
154     void join();
155 
156     /**
157      * Shut down any existing join(). Return true if successfully shut down, false otherwise
158      * (e.g. no join() is running). Will wait for the server to be fully
159      * shutdown.
160      *
161      * Warning: this will hang if it is called from its own thread.
162      */
163     [[nodiscard]] bool shutdown();
164 
165     /**
166      * For debugging!
167      */
168     std::vector<sp<RpcSession>> listSessions();
169     size_t numUninitializedSessions();
170 
171     ~RpcServer();
172 
173 private:
174     friend sp<RpcServer>;
175     explicit RpcServer(std::unique_ptr<RpcTransportCtx> ctx);
176 
177     void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override;
178     void onSessionIncomingThreadEnded() override;
179 
180     static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
181                                     const sockaddr_storage addr, socklen_t addrLen);
182     [[nodiscard]] status_t setupSocketServer(const RpcSocketAddress& address);
183 
184     const std::unique_ptr<RpcTransportCtx> mCtx;
185     size_t mMaxThreads = 1;
186     std::optional<uint32_t> mProtocolVersion;
187     base::unique_fd mServer; // socket we are accepting sessions on
188 
189     std::mutex mLock; // for below
190     std::unique_ptr<std::thread> mJoinThread;
191     bool mJoinThreadRunning = false;
192     std::map<std::thread::id, std::thread> mConnectingThreads;
193     sp<IBinder> mRootObject;
194     wp<IBinder> mRootObjectWeak;
195     std::function<sp<IBinder>(const sockaddr*, socklen_t)> mRootObjectFactory;
196     std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
197     std::unique_ptr<FdTrigger> mShutdownTrigger;
198     std::condition_variable mShutdownCv;
199 };
200 
201 } // namespace android
202