xref: /aosp_15_r20/frameworks/native/libs/binder/rust/rpcbinder/src/server/android.rs (revision 38e8c45f13ce32b0dcecb25141ffecaf386fa17f)
1 /*
2  * Copyright (C) 2024 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 use crate::session::FileDescriptorTransportMode;
18 use binder::{unstable_api::AsNative, SpIBinder};
19 use binder_rpc_unstable_bindgen::ARpcServer;
20 use foreign_types::{foreign_type, ForeignType, ForeignTypeRef};
21 use std::ffi::{c_uint, CString};
22 use std::io::{Error, ErrorKind};
23 use std::os::unix::io::{IntoRawFd, OwnedFd};
24 
25 foreign_type! {
26     type CType = binder_rpc_unstable_bindgen::ARpcServer;
27     fn drop = binder_rpc_unstable_bindgen::ARpcServer_free;
28 
29     /// A type that represents a foreign instance of RpcServer.
30     #[derive(Debug)]
31     pub struct RpcServer;
32     /// A borrowed RpcServer.
33     pub struct RpcServerRef;
34 }
35 
36 /// SAFETY: The opaque handle can be cloned freely.
37 unsafe impl Send for RpcServer {}
38 /// SAFETY: The underlying C++ RpcServer class is thread-safe.
39 unsafe impl Sync for RpcServer {}
40 
41 impl RpcServer {
42     /// Creates a binder RPC server, serving the supplied binder service implementation on the given
43     /// vsock port. Only connections from the given CID are accepted.
44     ///
45     /// Set `cid` to [`libc::VMADDR_CID_ANY`] to accept connections from any client.
46     /// Set `cid` to [`libc::VMADDR_CID_LOCAL`] to only bind to the local vsock interface.
47     /// Set `port` to [`libc::VMADDR_PORT_ANY`] to pick an ephemeral port.
48     /// The assigned port is returned with RpcServer.
new_vsock( mut service: SpIBinder, cid: u32, port: u32, ) -> Result<(RpcServer, u32 ), Error>49     pub fn new_vsock(
50         mut service: SpIBinder,
51         cid: u32,
52         port: u32,
53     ) -> Result<(RpcServer, u32 /* assigned_port */), Error> {
54         let service = service.as_native_mut();
55 
56         let mut assigned_port: c_uint = 0;
57         // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
58         // Plus the binder objects are threadsafe.
59         let server = unsafe {
60             Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newVsock(
61                 service,
62                 cid,
63                 port,
64                 &mut assigned_port,
65             ))?
66         };
67         Ok((server, assigned_port as _))
68     }
69 
70     /// Creates a binder RPC server, serving the supplied binder service implementation on the given
71     /// socket file descriptor. The socket should be bound to an address before calling this
72     /// function.
new_bound_socket( mut service: SpIBinder, socket_fd: OwnedFd, ) -> Result<RpcServer, Error>73     pub fn new_bound_socket(
74         mut service: SpIBinder,
75         socket_fd: OwnedFd,
76     ) -> Result<RpcServer, Error> {
77         let service = service.as_native_mut();
78 
79         // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
80         // Plus the binder objects are threadsafe.
81         // The server takes ownership of the socket FD.
82         unsafe {
83             Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newBoundSocket(
84                 service,
85                 socket_fd.into_raw_fd(),
86             ))
87         }
88     }
89 
90     /// Creates a binder RPC server that bootstraps sessions using an existing Unix domain socket
91     /// pair, with a given root IBinder object. Callers should create a pair of SOCK_STREAM Unix
92     /// domain sockets, pass one to the server and the other to the client. Multiple client session
93     /// can be created from the client end of the pair.
new_unix_domain_bootstrap( mut service: SpIBinder, bootstrap_fd: OwnedFd, ) -> Result<RpcServer, Error>94     pub fn new_unix_domain_bootstrap(
95         mut service: SpIBinder,
96         bootstrap_fd: OwnedFd,
97     ) -> Result<RpcServer, Error> {
98         let service = service.as_native_mut();
99 
100         // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
101         // Plus the binder objects are threadsafe.
102         // The server takes ownership of the bootstrap FD.
103         unsafe {
104             Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newUnixDomainBootstrap(
105                 service,
106                 bootstrap_fd.into_raw_fd(),
107             ))
108         }
109     }
110 
111     /// Creates a binder RPC server, serving the supplied binder service implementation on the given
112     /// IP address and port.
new_inet(mut service: SpIBinder, address: &str, port: u32) -> Result<RpcServer, Error>113     pub fn new_inet(mut service: SpIBinder, address: &str, port: u32) -> Result<RpcServer, Error> {
114         let address = match CString::new(address) {
115             Ok(s) => s,
116             Err(e) => {
117                 log::error!("Cannot convert {} to CString. Error: {:?}", address, e);
118                 return Err(Error::from(ErrorKind::InvalidInput));
119             }
120         };
121         let service = service.as_native_mut();
122 
123         // SAFETY: Service ownership is transferring to the server and won't be valid afterward.
124         // Plus the binder objects are threadsafe.
125         unsafe {
126             Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newInet(
127                 service,
128                 address.as_ptr(),
129                 port,
130             ))
131         }
132     }
133 
checked_from_ptr(ptr: *mut ARpcServer) -> Result<RpcServer, Error>134     unsafe fn checked_from_ptr(ptr: *mut ARpcServer) -> Result<RpcServer, Error> {
135         if ptr.is_null() {
136             return Err(Error::new(ErrorKind::Other, "Failed to start server"));
137         }
138         // SAFETY: Our caller must pass us a valid or null pointer, and we've checked that it's not
139         // null.
140         Ok(unsafe { RpcServer::from_ptr(ptr) })
141     }
142 }
143 
144 impl RpcServerRef {
145     /// Sets the list of file descriptor transport modes supported by this server.
set_supported_file_descriptor_transport_modes( &self, modes: &[FileDescriptorTransportMode], )146     pub fn set_supported_file_descriptor_transport_modes(
147         &self,
148         modes: &[FileDescriptorTransportMode],
149     ) {
150         // SAFETY: Does not keep the pointer after returning does, nor does it
151         // read past its boundary. Only passes the 'self' pointer as an opaque handle.
152         unsafe {
153             binder_rpc_unstable_bindgen::ARpcServer_setSupportedFileDescriptorTransportModes(
154                 self.as_ptr(),
155                 modes.as_ptr(),
156                 modes.len(),
157             )
158         }
159     }
160 
161     /// Sets the max number of threads this Server uses for incoming client connections.
162     ///
163     /// This must be called before adding a client session. This corresponds
164     /// to the number of incoming connections to RpcSession objects in the
165     /// server, which will correspond to the number of outgoing connections
166     /// in client RpcSession objects. Specifically this is useful for handling
167     /// client-side callback connections.
168     ///
169     /// If this is not specified, this will be a single-threaded server.
set_max_threads(&self, count: usize)170     pub fn set_max_threads(&self, count: usize) {
171         // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer.
172         unsafe { binder_rpc_unstable_bindgen::ARpcServer_setMaxThreads(self.as_ptr(), count) };
173     }
174 
175     /// Starts a new background thread and calls join(). Returns immediately.
start(&self)176     pub fn start(&self) {
177         // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer.
178         unsafe { binder_rpc_unstable_bindgen::ARpcServer_start(self.as_ptr()) };
179     }
180 
181     /// Joins the RpcServer thread. The call blocks until the server terminates.
182     /// This must be called from exactly one thread.
join(&self)183     pub fn join(&self) {
184         // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer.
185         unsafe { binder_rpc_unstable_bindgen::ARpcServer_join(self.as_ptr()) };
186     }
187 
188     /// Shuts down the running RpcServer. Can be called multiple times and from
189     /// multiple threads. Called automatically during drop().
shutdown(&self) -> Result<(), Error>190     pub fn shutdown(&self) -> Result<(), Error> {
191         // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer.
192         if unsafe { binder_rpc_unstable_bindgen::ARpcServer_shutdown(self.as_ptr()) } {
193             Ok(())
194         } else {
195             Err(Error::from(ErrorKind::UnexpectedEof))
196         }
197     }
198 }
199