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::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. new_vsock(mut service: SpIBinder, cid: u32, port: u32) -> Result<RpcServer, Error>47 pub fn new_vsock(mut service: SpIBinder, cid: u32, port: u32) -> Result<RpcServer, Error> { 48 let service = service.as_native_mut(); 49 50 // SAFETY: Service ownership is transferring to the server and won't be valid afterward. 51 // Plus the binder objects are threadsafe. 52 unsafe { 53 Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newVsock( 54 service, cid, port, 55 )) 56 } 57 } 58 59 /// Creates a binder RPC server, serving the supplied binder service implementation on the given 60 /// socket file descriptor. The socket should be bound to an address before calling this 61 /// function. new_bound_socket( mut service: SpIBinder, socket_fd: OwnedFd, ) -> Result<RpcServer, Error>62 pub fn new_bound_socket( 63 mut service: SpIBinder, 64 socket_fd: OwnedFd, 65 ) -> Result<RpcServer, Error> { 66 let service = service.as_native_mut(); 67 68 // SAFETY: Service ownership is transferring to the server and won't be valid afterward. 69 // Plus the binder objects are threadsafe. 70 // The server takes ownership of the socket FD. 71 unsafe { 72 Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newBoundSocket( 73 service, 74 socket_fd.into_raw_fd(), 75 )) 76 } 77 } 78 79 /// Creates a binder RPC server that bootstraps sessions using an existing Unix domain socket 80 /// pair, with a given root IBinder object. Callers should create a pair of SOCK_STREAM Unix 81 /// domain sockets, pass one to the server and the other to the client. Multiple client session 82 /// can be created from the client end of the pair. new_unix_domain_bootstrap( mut service: SpIBinder, bootstrap_fd: OwnedFd, ) -> Result<RpcServer, Error>83 pub fn new_unix_domain_bootstrap( 84 mut service: SpIBinder, 85 bootstrap_fd: OwnedFd, 86 ) -> Result<RpcServer, Error> { 87 let service = service.as_native_mut(); 88 89 // SAFETY: Service ownership is transferring to the server and won't be valid afterward. 90 // Plus the binder objects are threadsafe. 91 // The server takes ownership of the bootstrap FD. 92 unsafe { 93 Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newUnixDomainBootstrap( 94 service, 95 bootstrap_fd.into_raw_fd(), 96 )) 97 } 98 } 99 100 /// Creates a binder RPC server, serving the supplied binder service implementation on the given 101 /// IP address and port. new_inet(mut service: SpIBinder, address: &str, port: u32) -> Result<RpcServer, Error>102 pub fn new_inet(mut service: SpIBinder, address: &str, port: u32) -> Result<RpcServer, Error> { 103 let address = match CString::new(address) { 104 Ok(s) => s, 105 Err(e) => { 106 log::error!("Cannot convert {} to CString. Error: {:?}", address, e); 107 return Err(Error::from(ErrorKind::InvalidInput)); 108 } 109 }; 110 let service = service.as_native_mut(); 111 112 // SAFETY: Service ownership is transferring to the server and won't be valid afterward. 113 // Plus the binder objects are threadsafe. 114 unsafe { 115 Self::checked_from_ptr(binder_rpc_unstable_bindgen::ARpcServer_newInet( 116 service, 117 address.as_ptr(), 118 port, 119 )) 120 } 121 } 122 checked_from_ptr(ptr: *mut ARpcServer) -> Result<RpcServer, Error>123 unsafe fn checked_from_ptr(ptr: *mut ARpcServer) -> Result<RpcServer, Error> { 124 if ptr.is_null() { 125 return Err(Error::new(ErrorKind::Other, "Failed to start server")); 126 } 127 // SAFETY: Our caller must pass us a valid or null pointer, and we've checked that it's not 128 // null. 129 Ok(unsafe { RpcServer::from_ptr(ptr) }) 130 } 131 } 132 133 impl RpcServerRef { 134 /// Sets the list of file descriptor transport modes supported by this server. set_supported_file_descriptor_transport_modes( &self, modes: &[FileDescriptorTransportMode], )135 pub fn set_supported_file_descriptor_transport_modes( 136 &self, 137 modes: &[FileDescriptorTransportMode], 138 ) { 139 // SAFETY: Does not keep the pointer after returning does, nor does it 140 // read past its boundary. Only passes the 'self' pointer as an opaque handle. 141 unsafe { 142 binder_rpc_unstable_bindgen::ARpcServer_setSupportedFileDescriptorTransportModes( 143 self.as_ptr(), 144 modes.as_ptr(), 145 modes.len(), 146 ) 147 } 148 } 149 150 /// Sets the max number of threads this Server uses for incoming client connections. 151 /// 152 /// This must be called before adding a client session. This corresponds 153 /// to the number of incoming connections to RpcSession objects in the 154 /// server, which will correspond to the number of outgoing connections 155 /// in client RpcSession objects. Specifically this is useful for handling 156 /// client-side callback connections. 157 /// 158 /// If this is not specified, this will be a single-threaded server. set_max_threads(&self, count: usize)159 pub fn set_max_threads(&self, count: usize) { 160 // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. 161 unsafe { binder_rpc_unstable_bindgen::ARpcServer_setMaxThreads(self.as_ptr(), count) }; 162 } 163 164 /// Starts a new background thread and calls join(). Returns immediately. start(&self)165 pub fn start(&self) { 166 // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. 167 unsafe { binder_rpc_unstable_bindgen::ARpcServer_start(self.as_ptr()) }; 168 } 169 170 /// Joins the RpcServer thread. The call blocks until the server terminates. 171 /// This must be called from exactly one thread. join(&self)172 pub fn join(&self) { 173 // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. 174 unsafe { binder_rpc_unstable_bindgen::ARpcServer_join(self.as_ptr()) }; 175 } 176 177 /// Shuts down the running RpcServer. Can be called multiple times and from 178 /// multiple threads. Called automatically during drop(). shutdown(&self) -> Result<(), Error>179 pub fn shutdown(&self) -> Result<(), Error> { 180 // SAFETY: RpcServerRef wraps a valid pointer to an ARpcServer. 181 if unsafe { binder_rpc_unstable_bindgen::ARpcServer_shutdown(self.as_ptr()) } { 182 Ok(()) 183 } else { 184 Err(Error::from(ErrorKind::UnexpectedEof)) 185 } 186 } 187 } 188