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