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