• 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 <utils/Errors.h>
22 #include <utils/RefBase.h>
23 
24 #include <mutex>
25 #include <thread>
26 
27 // WARNING: This is a feature which is still in development, and it is subject
28 // to radical change. Any production use of this may subject your code to any
29 // number of problems.
30 
31 namespace android {
32 
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 {
48 public:
49     static sp<RpcServer> make();
50 
51     /**
52      * This represents a session for responses, e.g.:
53      *
54      *     process A serves binder a
55      *     process B opens a session to process A
56      *     process B makes binder b and sends it to A
57      *     A uses this 'back session' to send things back to B
58      */
59     [[nodiscard]] bool setupUnixDomainServer(const char* path);
60 
61     /**
62      * Creates an RPC server at the current port.
63      */
64     [[nodiscard]] bool setupVsockServer(unsigned int port);
65 
66     /**
67      * Creates an RPC server at the current port using IPv4.
68      *
69      * TODO(b/182914638): IPv6 support
70      *
71      * Set |port| to 0 to pick an ephemeral port; see discussion of
72      * /proc/sys/net/ipv4/ip_local_port_range in ip(7). In this case, |assignedPort|
73      * will be set to the picked port number, if it is not null.
74      */
75     [[nodiscard]] bool setupInetServer(unsigned int port, unsigned int* assignedPort);
76 
77     /**
78      * If setup*Server has been successful, return true. Otherwise return false.
79      */
80     [[nodiscard]] bool hasServer();
81 
82     /**
83      * If hasServer(), return the server FD. Otherwise return invalid FD.
84      */
85     [[nodiscard]] base::unique_fd releaseServer();
86 
87     /**
88      * Set up server using an external FD previously set up by releaseServer().
89      * Return false if there's already a server.
90      */
91     bool setupExternalServer(base::unique_fd serverFd);
92 
93     void iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
94 
95     /**
96      * This must be called before adding a client session.
97      *
98      * If this is not specified, this will be a single-threaded server.
99      *
100      * TODO(b/185167543): these are currently created per client, but these
101      * should be shared.
102      */
103     void setMaxThreads(size_t threads);
104     size_t getMaxThreads();
105 
106     /**
107      * The root object can be retrieved by any client, without any
108      * authentication. TODO(b/183988761)
109      *
110      * Holds a strong reference to the root object.
111      */
112     void setRootObject(const sp<IBinder>& binder);
113     /**
114      * Holds a weak reference to the root object.
115      */
116     void setRootObjectWeak(const wp<IBinder>& binder);
117     sp<IBinder> getRootObject();
118 
119     /**
120      * You must have at least one client session before calling this.
121      *
122      * TODO(b/185167543): way to shut down?
123      */
124     void join();
125 
126     /**
127      * Accept one connection on this server. You must have at least one client
128      * session before calling this.
129      */
130     [[nodiscard]] bool acceptOne();
131 
132     /**
133      * For debugging!
134      */
135     std::vector<sp<RpcSession>> listSessions();
136     size_t numUninitializedSessions();
137 
138     ~RpcServer();
139 
140     // internal use only
141 
142     void onSessionTerminating(const sp<RpcSession>& session);
143 
144 private:
145     friend sp<RpcServer>;
146     RpcServer();
147 
148     void establishConnection(sp<RpcServer>&& session, base::unique_fd clientFd);
149     bool setupSocketServer(const RpcSocketAddress& address);
150 
151     bool mAgreedExperimental = false;
152     bool mStarted = false; // TODO(b/185167543): support dynamically added clients
153     size_t mMaxThreads = 1;
154     base::unique_fd mServer; // socket we are accepting sessions on
155 
156     std::mutex mLock; // for below
157     std::map<std::thread::id, std::thread> mConnectingThreads;
158     sp<IBinder> mRootObject;
159     wp<IBinder> mRootObjectWeak;
160     std::map<int32_t, sp<RpcSession>> mSessions;
161     int32_t mSessionIdCounter = 0;
162 };
163 
164 } // namespace android
165