1 //! This module is a simple GATT server that shares the ATT channel with the 2 //! existing C++ GATT client. 3 4 mod att_database; 5 pub mod att_server_bearer; 6 pub mod gatt_database; 7 mod indication_handler; 8 mod request_handler; 9 pub mod services; 10 mod transactions; 11 12 mod command_handler; 13 pub mod isolation_manager; 14 #[cfg(test)] 15 mod test; 16 17 use std::{ 18 collections::HashMap, 19 rc::Rc, 20 sync::{Arc, Mutex, MutexGuard}, 21 }; 22 23 use crate::{ 24 core::shared_box::{SharedBox, WeakBox, WeakBoxRef}, 25 gatt::server::gatt_database::GattDatabase, 26 }; 27 28 use self::{ 29 super::ids::ServerId, 30 att_server_bearer::AttServerBearer, 31 gatt_database::{AttDatabaseImpl, GattServiceWithHandle}, 32 isolation_manager::IsolationManager, 33 services::register_builtin_services, 34 }; 35 36 use super::{ 37 callbacks::RawGattDatastore, 38 channel::AttTransport, 39 ids::{AdvertiserId, AttHandle, TransportIndex}, 40 }; 41 use anyhow::{anyhow, bail, Result}; 42 use bt_common::init_flags::always_use_private_gatt_for_debugging_is_enabled; 43 use log::info; 44 45 pub use indication_handler::IndicationError; 46 47 #[allow(missing_docs)] 48 pub struct GattModule { 49 connections: HashMap<TransportIndex, GattConnection>, 50 databases: HashMap<ServerId, SharedBox<GattDatabase>>, 51 transport: Rc<dyn AttTransport>, 52 // NOTE: this is logically owned by the GattModule. We share it behind a Mutex just so we 53 // can use it as part of the Arbiter. Once the Arbiter is removed, this should be owned 54 // fully by the GattModule. 55 isolation_manager: Arc<Mutex<IsolationManager>>, 56 } 57 58 struct GattConnection { 59 bearer: SharedBox<AttServerBearer<AttDatabaseImpl>>, 60 database: WeakBox<GattDatabase>, 61 } 62 63 impl GattModule { 64 /// Constructor. new( transport: Rc<dyn AttTransport>, isolation_manager: Arc<Mutex<IsolationManager>>, ) -> Self65 pub fn new( 66 transport: Rc<dyn AttTransport>, 67 isolation_manager: Arc<Mutex<IsolationManager>>, 68 ) -> Self { 69 Self { 70 connections: HashMap::new(), 71 databases: HashMap::new(), 72 transport, 73 isolation_manager, 74 } 75 } 76 77 /// Handle LE link connect on_le_connect( &mut self, tcb_idx: TransportIndex, advertiser_id: Option<AdvertiserId>, ) -> Result<()>78 pub fn on_le_connect( 79 &mut self, 80 tcb_idx: TransportIndex, 81 advertiser_id: Option<AdvertiserId>, 82 ) -> Result<()> { 83 info!("connected on tcb_idx {tcb_idx:?}"); 84 self.isolation_manager.lock().unwrap().on_le_connect(tcb_idx, advertiser_id); 85 86 let Some(server_id) = self.isolation_manager.lock().unwrap().get_server_id(tcb_idx) else { 87 bail!("non-isolated servers are not yet supported (b/274945531)") 88 }; 89 let database = self.databases.get(&server_id); 90 let Some(database) = database else { 91 bail!("got connection to {server_id:?} but this server does not exist!"); 92 }; 93 94 let transport = self.transport.clone(); 95 let bearer = SharedBox::new(AttServerBearer::new( 96 database.get_att_database(tcb_idx), 97 move |packet| transport.send_packet(tcb_idx, packet), 98 )); 99 database.on_bearer_ready(tcb_idx, bearer.as_ref()); 100 self.connections.insert(tcb_idx, GattConnection { bearer, database: database.downgrade() }); 101 Ok(()) 102 } 103 104 /// Handle an LE link disconnect on_le_disconnect(&mut self, tcb_idx: TransportIndex) -> Result<()>105 pub fn on_le_disconnect(&mut self, tcb_idx: TransportIndex) -> Result<()> { 106 info!("disconnected conn_id {tcb_idx:?}"); 107 self.isolation_manager.lock().unwrap().on_le_disconnect(tcb_idx); 108 let connection = self.connections.remove(&tcb_idx); 109 let Some(connection) = connection else { 110 bail!("got disconnection from {tcb_idx:?} but bearer does not exist"); 111 }; 112 drop(connection.bearer); 113 connection.database.with(|db| db.map(|db| db.on_bearer_dropped(tcb_idx))); 114 Ok(()) 115 } 116 117 /// Register a new GATT service on a given server register_gatt_service( &mut self, server_id: ServerId, service: GattServiceWithHandle, datastore: impl RawGattDatastore + 'static, ) -> Result<()>118 pub fn register_gatt_service( 119 &mut self, 120 server_id: ServerId, 121 service: GattServiceWithHandle, 122 datastore: impl RawGattDatastore + 'static, 123 ) -> Result<()> { 124 self.databases 125 .get(&server_id) 126 .ok_or_else(|| anyhow!("server {server_id:?} not opened"))? 127 .add_service_with_handles(service, Rc::new(datastore)) 128 } 129 130 /// Unregister an existing GATT service on a given server unregister_gatt_service( &mut self, server_id: ServerId, service_handle: AttHandle, ) -> Result<()>131 pub fn unregister_gatt_service( 132 &mut self, 133 server_id: ServerId, 134 service_handle: AttHandle, 135 ) -> Result<()> { 136 self.databases 137 .get(&server_id) 138 .ok_or_else(|| anyhow!("server {server_id:?} not opened"))? 139 .remove_service_at_handle(service_handle) 140 } 141 142 /// Open a GATT server open_gatt_server(&mut self, server_id: ServerId) -> Result<()>143 pub fn open_gatt_server(&mut self, server_id: ServerId) -> Result<()> { 144 let mut db = GattDatabase::new(); 145 register_builtin_services(&mut db)?; 146 let old = self.databases.insert(server_id, db.into()); 147 if old.is_some() { 148 bail!("GATT server {server_id:?} already exists but was re-opened, clobbering old value...") 149 } 150 Ok(()) 151 } 152 153 /// Close a GATT server close_gatt_server(&mut self, server_id: ServerId) -> Result<()>154 pub fn close_gatt_server(&mut self, server_id: ServerId) -> Result<()> { 155 let old = self.databases.remove(&server_id); 156 if old.is_none() { 157 bail!("GATT server {server_id:?} did not exist") 158 }; 159 160 if !always_use_private_gatt_for_debugging_is_enabled() { 161 self.isolation_manager.lock().unwrap().clear_server(server_id); 162 } 163 164 Ok(()) 165 } 166 167 /// Get an ATT bearer for a particular connection get_bearer( &self, tcb_idx: TransportIndex, ) -> Option<WeakBoxRef<AttServerBearer<AttDatabaseImpl>>>168 pub fn get_bearer( 169 &self, 170 tcb_idx: TransportIndex, 171 ) -> Option<WeakBoxRef<AttServerBearer<AttDatabaseImpl>>> { 172 self.connections.get(&tcb_idx).map(|x| x.bearer.as_ref()) 173 } 174 175 /// Get the IsolationManager to manage associations between servers + advertisers get_isolation_manager(&mut self) -> MutexGuard<'_, IsolationManager>176 pub fn get_isolation_manager(&mut self) -> MutexGuard<'_, IsolationManager> { 177 self.isolation_manager.lock().unwrap() 178 } 179 } 180