blob: 3d22002c789b258e96070f14fe8a2ad837997f0d [file] [log] [blame]
Steven Moreland5553ac42020-11-11 02:14:45 +00001/*
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/RpcAddress.h>
21#include <utils/Errors.h>
22#include <utils/RefBase.h>
23
Steven Moreland736664b2021-05-01 04:27:25 +000024#include <map>
Steven Moreland5553ac42020-11-11 02:14:45 +000025#include <optional>
Steven Moreland736664b2021-05-01 04:27:25 +000026#include <thread>
Steven Moreland5553ac42020-11-11 02:14:45 +000027#include <vector>
28
29// WARNING: This is a feature which is still in development, and it is subject
30// to radical change. Any production use of this may subject your code to any
31// number of problems.
32
33namespace android {
34
35class Parcel;
36class RpcServer;
Steven Moreland611d15f2021-05-01 01:28:27 +000037class RpcSocketAddress;
Steven Moreland5553ac42020-11-11 02:14:45 +000038class RpcState;
39
40/**
Steven Morelandbdb53ab2021-05-05 17:57:41 +000041 * This represents a session (group of connections) between a client
42 * and a server. Multiple connections are needed for multiple parallel "binder"
43 * calls which may also have nested calls.
Steven Moreland5553ac42020-11-11 02:14:45 +000044 */
Steven Morelandbdb53ab2021-05-05 17:57:41 +000045class RpcSession final : public virtual RefBase {
Steven Moreland5553ac42020-11-11 02:14:45 +000046public:
Steven Morelandbdb53ab2021-05-05 17:57:41 +000047 static sp<RpcSession> make();
Steven Moreland5553ac42020-11-11 02:14:45 +000048
49 /**
Steven Moreland5553ac42020-11-11 02:14:45 +000050 * This should be called once per thread, matching 'join' in the remote
51 * process.
52 */
Steven Morelandf137de92021-04-24 01:54:26 +000053 [[nodiscard]] bool setupUnixDomainClient(const char* path);
Steven Moreland5553ac42020-11-11 02:14:45 +000054
Steven Morelandc1635952021-04-01 16:20:47 +000055 /**
Steven Morelandc1635952021-04-01 16:20:47 +000056 * Connects to an RPC server at the CVD & port.
57 */
Steven Morelandf137de92021-04-24 01:54:26 +000058 [[nodiscard]] bool setupVsockClient(unsigned int cvd, unsigned int port);
Steven Morelandc1635952021-04-01 16:20:47 +000059
Steven Moreland5553ac42020-11-11 02:14:45 +000060 /**
Yifan Hong0d2bd112021-04-13 17:38:36 -070061 * Connects to an RPC server at the given address and port.
62 */
Steven Morelandf137de92021-04-24 01:54:26 +000063 [[nodiscard]] bool setupInetClient(const char* addr, unsigned int port);
Yifan Hong0d2bd112021-04-13 17:38:36 -070064
65 /**
Steven Morelandd47b32c2021-04-13 02:03:08 +000066 * For debugging!
67 *
Steven Morelandbdb53ab2021-05-05 17:57:41 +000068 * Sets up an empty connection. All queries to this connection which require a
Steven Morelandd47b32c2021-04-13 02:03:08 +000069 * response will never be satisfied. All data sent here will be
70 * unceremoniously cast down the bottomless pit, /dev/null.
71 */
72 [[nodiscard]] bool addNullDebuggingClient();
73
74 /**
Steven Morelandbdb53ab2021-05-05 17:57:41 +000075 * Query the other side of the session for the root object hosted by that
Steven Moreland5553ac42020-11-11 02:14:45 +000076 * process's RpcServer (if one exists)
77 */
78 sp<IBinder> getRootObject();
79
Steven Morelandf137de92021-04-24 01:54:26 +000080 /**
Steven Morelandbdb53ab2021-05-05 17:57:41 +000081 * Query the other side of the session for the maximum number of threads
Steven Morelandf137de92021-04-24 01:54:26 +000082 * it supports (maximum number of concurrent non-nested synchronous transactions)
83 */
Steven Moreland1be91352021-05-11 22:12:15 +000084 status_t getRemoteMaxThreads(size_t* maxThreads);
Steven Morelandf137de92021-04-24 01:54:26 +000085
Steven Moreland5553ac42020-11-11 02:14:45 +000086 [[nodiscard]] status_t transact(const RpcAddress& address, uint32_t code, const Parcel& data,
87 Parcel* reply, uint32_t flags);
88 [[nodiscard]] status_t sendDecStrong(const RpcAddress& address);
89
Steven Morelandbdb53ab2021-05-05 17:57:41 +000090 ~RpcSession();
Steven Moreland5553ac42020-11-11 02:14:45 +000091
Steven Moreland5553ac42020-11-11 02:14:45 +000092 wp<RpcServer> server();
93
94 // internal only
95 const std::unique_ptr<RpcState>& state() { return mState; }
96
Steven Moreland7c5e6c22021-05-01 02:55:20 +000097 class PrivateAccessorForId {
98 private:
Steven Morelandbdb53ab2021-05-05 17:57:41 +000099 friend class RpcSession;
Steven Moreland7c5e6c22021-05-01 02:55:20 +0000100 friend class RpcState;
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000101 explicit PrivateAccessorForId(const RpcSession* session) : mSession(session) {}
Steven Moreland7c5e6c22021-05-01 02:55:20 +0000102
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000103 const std::optional<int32_t> get() { return mSession->mId; }
Steven Moreland7c5e6c22021-05-01 02:55:20 +0000104
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000105 const RpcSession* mSession;
Steven Moreland7c5e6c22021-05-01 02:55:20 +0000106 };
107 PrivateAccessorForId getPrivateAccessorForId() const { return PrivateAccessorForId(this); }
108
Steven Moreland5553ac42020-11-11 02:14:45 +0000109private:
Steven Moreland7c5e6c22021-05-01 02:55:20 +0000110 friend PrivateAccessorForId;
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000111 friend sp<RpcSession>;
Steven Morelandf137de92021-04-24 01:54:26 +0000112 friend RpcServer;
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000113 RpcSession();
Steven Moreland5553ac42020-11-11 02:14:45 +0000114
Steven Morelande47511f2021-05-20 00:07:41 +0000115 /** This is not a pipe. */
116 struct FdTrigger {
117 static std::unique_ptr<FdTrigger> make();
118 /**
119 * poll() on this fd for POLLHUP to get notification when trigger is called
120 */
121 base::borrowed_fd readFd() const { return mRead; }
Steven Moreland4ec3c432021-05-20 00:32:47 +0000122
Steven Morelande47511f2021-05-20 00:07:41 +0000123 /**
124 * Close the write end of the pipe so that the read end receives POLLHUP.
125 */
126 void trigger();
127
Steven Moreland4ec3c432021-05-20 00:32:47 +0000128 /**
129 * Poll for a read event.
130 *
131 * Return:
132 * true - time to read!
133 * false - trigger happened
134 */
135 bool triggerablePollRead(base::borrowed_fd fd);
136
Steven Moreland9d11b922021-05-20 01:22:58 +0000137 /**
138 * Read, but allow the read to be interrupted by this trigger.
139 *
140 * Return:
141 * true - read succeeded at 'size'
142 * false - interrupted (failure or trigger)
143 */
144 bool interruptableRecv(base::borrowed_fd fd, void* data, size_t size);
145
Steven Morelande47511f2021-05-20 00:07:41 +0000146 private:
147 base::unique_fd mWrite;
148 base::unique_fd mRead;
149 };
150
Steven Moreland7c5e6c22021-05-01 02:55:20 +0000151 status_t readId();
152
Steven Moreland5802c2b2021-05-12 20:13:04 +0000153 // transfer ownership of thread
154 void preJoin(std::thread thread);
155 // join on thread passed to preJoin
156 void join(base::unique_fd client);
Steven Morelandee78e762021-05-05 21:12:51 +0000157 void terminateLocked();
Steven Morelandf137de92021-04-24 01:54:26 +0000158
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000159 struct RpcConnection : public RefBase {
Steven Moreland5553ac42020-11-11 02:14:45 +0000160 base::unique_fd fd;
161
162 // whether this or another thread is currently using this fd to make
163 // or receive transactions.
164 std::optional<pid_t> exclusiveTid;
165 };
166
Steven Moreland611d15f2021-05-01 01:28:27 +0000167 bool setupSocketClient(const RpcSocketAddress& address);
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000168 bool setupOneSocketClient(const RpcSocketAddress& address, int32_t sessionId);
Steven Morelandc8c256b2021-05-11 22:59:09 +0000169 void addClientConnection(base::unique_fd fd);
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000170 void setForServer(const wp<RpcServer>& server, int32_t sessionId);
171 sp<RpcConnection> assignServerToThisThread(base::unique_fd fd);
172 bool removeServerConnection(const sp<RpcConnection>& connection);
Steven Morelandaf816d82021-04-19 23:11:33 +0000173
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000174 enum class ConnectionUse {
Steven Moreland5553ac42020-11-11 02:14:45 +0000175 CLIENT,
176 CLIENT_ASYNC,
177 CLIENT_REFCOUNT,
Steven Moreland5553ac42020-11-11 02:14:45 +0000178 };
179
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000180 // RAII object for session connection
181 class ExclusiveConnection {
Steven Moreland5553ac42020-11-11 02:14:45 +0000182 public:
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000183 explicit ExclusiveConnection(const sp<RpcSession>& session, ConnectionUse use);
184 ~ExclusiveConnection();
185 const base::unique_fd& fd() { return mConnection->fd; }
Steven Moreland5553ac42020-11-11 02:14:45 +0000186
187 private:
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000188 static void findConnection(pid_t tid, sp<RpcConnection>* exclusive,
189 sp<RpcConnection>* available,
190 std::vector<sp<RpcConnection>>& sockets,
191 size_t socketsIndexHint);
Steven Moreland5553ac42020-11-11 02:14:45 +0000192
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000193 sp<RpcSession> mSession; // avoid deallocation
194 sp<RpcConnection> mConnection;
Steven Moreland5553ac42020-11-11 02:14:45 +0000195
196 // whether this is being used for a nested transaction (being on the same
197 // thread guarantees we won't write in the middle of a message, the way
198 // the wire protocol is constructed guarantees this is safe).
199 bool mReentrant = false;
200 };
201
Steven Morelandbb543a82021-05-11 02:31:50 +0000202 // On the other side of a session, for each of mClientConnections here, there should
203 // be one of mServerConnections on the other side (and vice versa).
Steven Moreland5553ac42020-11-11 02:14:45 +0000204 //
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000205 // For the simplest session, a single server with one client, you would
Steven Moreland5553ac42020-11-11 02:14:45 +0000206 // have:
Steven Morelandbb543a82021-05-11 02:31:50 +0000207 // - the server has a single 'mServerConnections' and a thread listening on this
208 // - the client has a single 'mClientConnections' and makes calls to this
Steven Moreland5553ac42020-11-11 02:14:45 +0000209 // - here, when the client makes a call, the server can call back into it
210 // (nested calls), but outside of this, the client will only ever read
211 // calls from the server when it makes a call itself.
212 //
213 // For a more complicated case, the client might itself open up a thread to
214 // serve calls to the server at all times (e.g. if it hosts a callback)
215
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000216 wp<RpcServer> mForServer; // maybe null, for client sessions
Steven Moreland5553ac42020-11-11 02:14:45 +0000217
Steven Moreland7c5e6c22021-05-01 02:55:20 +0000218 // TODO(b/183988761): this shouldn't be guessable
219 std::optional<int32_t> mId;
220
Steven Moreland5553ac42020-11-11 02:14:45 +0000221 std::unique_ptr<RpcState> mState;
222
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000223 std::mutex mMutex; // for all below
Steven Moreland736664b2021-05-01 04:27:25 +0000224
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000225 std::condition_variable mAvailableConnectionCv; // for mWaitingThreads
Steven Moreland5553ac42020-11-11 02:14:45 +0000226 size_t mWaitingThreads = 0;
Steven Morelandbb543a82021-05-11 02:31:50 +0000227 // hint index into clients, ++ when sending an async transaction
228 size_t mClientConnectionsOffset = 0;
229 std::vector<sp<RpcConnection>> mClientConnections;
230 std::vector<sp<RpcConnection>> mServerConnections;
Steven Moreland736664b2021-05-01 04:27:25 +0000231
Steven Morelandbdb53ab2021-05-05 17:57:41 +0000232 // TODO(b/185167543): use for reverse sessions (allow client to also
233 // serve calls on a session).
234 // TODO(b/185167543): allow sharing between different sessions in a
Steven Morelandbb543a82021-05-11 02:31:50 +0000235 // process? (or combine with mServerConnections)
Steven Moreland736664b2021-05-01 04:27:25 +0000236 std::map<std::thread::id, std::thread> mThreads;
Steven Morelandee78e762021-05-05 21:12:51 +0000237 bool mTerminated = false;
Steven Moreland5553ac42020-11-11 02:14:45 +0000238};
239
240} // namespace android