1 /*
2  * Copyright (C) 2021 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 
17 #pragma once
18 
19 #include <sys/socket.h>
20 #include <stdint.h>
21 
22 extern "C" {
23 
24 struct AIBinder;
25 struct ARpcServer;
26 struct ARpcSession;
27 
28 enum class ARpcSession_FileDescriptorTransportMode {
29     None,
30     Unix,
31     Trusty,
32 };
33 
34 // Starts an RPC server on a given port and a given root IBinder object.
35 // The server will only accept connections from the given CID.
36 // Set `cid` to VMADDR_CID_ANY to accept connections from any client.
37 // Set `cid` to VMADDR_CID_LOCAL to only bind to the local vsock interface.
38 // Returns an opaque handle to the running server instance, or null if the server
39 // could not be started.
40 [[nodiscard]] ARpcServer* ARpcServer_newVsock(AIBinder* service, unsigned int cid,
41                                               unsigned int port);
42 
43 // Starts a Unix domain RPC server with an open raw socket file descriptor
44 // and a given root IBinder object.
45 // The socket should be created and bound to an address.
46 // Returns an opaque handle to the running server instance, or null if the server
47 // could not be started.
48 // The socket will be closed by the server once the server goes out of scope.
49 [[nodiscard]] ARpcServer* ARpcServer_newBoundSocket(AIBinder* service, int socketFd);
50 
51 // Starts an RPC server that bootstraps sessions using an existing Unix domain
52 // socket pair, with a given root IBinder object.
53 // Callers should create a pair of SOCK_STREAM Unix domain sockets, pass one to
54 // this function and the other to UnixDomainBootstrapClient(). Multiple client
55 // session can be created from the client end of the pair.
56 // Does not take ownership of `service`.
57 // Returns an opaque handle to the running server instance, or null if the server
58 // could not be started.
59 [[nodiscard]] ARpcServer* ARpcServer_newUnixDomainBootstrap(AIBinder* service, int bootstrapFd);
60 
61 // Starts an RPC server on a given IP address+port and a given IBinder object.
62 // Returns an opaque handle to the running server instance, or null if the server
63 // could not be started.
64 // Does not take ownership of `service`.
65 // Returns an opaque handle to the running service instance, or null if the server
66 // could not be started.
67 [[nodiscard]] ARpcServer* ARpcServer_newInet(AIBinder* service, const char* address,
68                                              unsigned int port);
69 
70 // Sets the list of supported file descriptor transport modes of this RPC server.
71 void ARpcServer_setSupportedFileDescriptorTransportModes(
72         ARpcServer* handle,
73         const ARpcSession_FileDescriptorTransportMode modes[],
74         size_t modes_len);
75 
76 // Sets the maximum number of threads that the Server will use for
77 // incoming client connections.
78 //
79 // This must be called before adding a client session. This corresponds
80 // to the number of incoming connections to RpcSession objects in the
81 // server, which will correspond to the number of outgoing connections
82 // in client RpcSession objects.
83 //
84 // If this is not specified, this will be a single-threaded server.
85 void ARpcServer_setMaxThreads(ARpcServer* server, size_t threads);
86 
87 // Runs ARpcServer_join() in a background thread. Immediately returns.
88 void ARpcServer_start(ARpcServer* server);
89 
90 // Joins the thread of a running RpcServer instance. At any given point, there
91 // can only be one thread calling ARpcServer_join().
92 // If a client needs to actively terminate join, call ARpcServer_shutdown() in
93 // a separate thread.
94 void ARpcServer_join(ARpcServer* server);
95 
96 // Shuts down any running ARpcServer_join().
97 [[nodiscard]] bool ARpcServer_shutdown(ARpcServer* server);
98 
99 // Frees the ARpcServer handle and drops the reference count on the underlying
100 // RpcServer instance. The handle must not be reused afterwards.
101 // This automatically calls ARpcServer_shutdown().
102 void ARpcServer_free(ARpcServer* server);
103 
104 // Allocates a new RpcSession object and returns an opaque handle to it.
105 [[nodiscard]] ARpcSession* ARpcSession_new();
106 
107 // Connects to an RPC server over vsock at a given CID on a given port.
108 // Returns the root Binder object of the server.
109 AIBinder* ARpcSession_setupVsockClient(ARpcSession* session, unsigned int cid,
110                                        unsigned int port);
111 
112 // Connects to an RPC server over a Unix Domain Socket of the given name.
113 // The final Unix Domain Socket path name is /dev/socket/`name`.
114 // Returns the root Binder object of the server.
115 AIBinder* ARpcSession_setupUnixDomainClient(ARpcSession* session, const char* name);
116 
117 // Connects to an RPC server over the given bootstrap Unix domain socket.
118 // Does NOT take ownership of `bootstrapFd`.
119 AIBinder* ARpcSession_setupUnixDomainBootstrapClient(ARpcSession* session,
120                                                      int bootstrapFd);
121 
122 // Connects to an RPC server over an INET socket at a given IP address on a given port.
123 // Returns the root Binder object of the server.
124 AIBinder* ARpcSession_setupInet(ARpcSession* session, const char* address, unsigned int port);
125 
126 // Connects to an RPC server with preconnected file descriptors.
127 //
128 // requestFd should connect to the server and return a valid file descriptor, or
129 // -1 if connection fails.
130 //
131 // param will be passed to requestFd. Callers can use param to pass contexts to
132 // the requestFd function.
133 AIBinder* ARpcSession_setupPreconnectedClient(ARpcSession* session,
134                                               int (*requestFd)(void* param),
135                                               void* param);
136 
137 // Sets the file descriptor transport mode for this session.
138 void ARpcSession_setFileDescriptorTransportMode(ARpcSession* session,
139                                                 ARpcSession_FileDescriptorTransportMode mode);
140 
141 // Sets the maximum number of incoming threads, to service connections.
142 void ARpcSession_setMaxIncomingThreads(ARpcSession* session, size_t threads);
143 
144 // Sets the maximum number of outgoing connections.
145 void ARpcSession_setMaxOutgoingConnections(ARpcSession* session, size_t connections);
146 
147 // Decrements the refcount of the underlying RpcSession object.
148 void ARpcSession_free(ARpcSession* session);
149 }
150