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 #[cfg(test)] 14 mod test; 15 16 use std::{collections::HashMap, rc::Rc}; 17 18 use crate::{ 19 core::shared_box::{SharedBox, WeakBox, WeakBoxRef}, 20 gatt::{ids::ConnectionId, server::gatt_database::GattDatabase}, 21 }; 22 23 use self::{ 24 super::ids::ServerId, 25 att_server_bearer::AttServerBearer, 26 gatt_database::{AttDatabaseImpl, GattServiceWithHandle}, 27 services::register_builtin_services, 28 }; 29 30 use super::{ 31 callbacks::RawGattDatastore, 32 channel::AttTransport, 33 ids::{AttHandle, TransportIndex}, 34 }; 35 use anyhow::{anyhow, bail, Result}; 36 use log::info; 37 38 pub use indication_handler::IndicationError; 39 40 #[allow(missing_docs)] 41 pub struct GattModule { 42 connections: HashMap<TransportIndex, GattConnection>, 43 databases: HashMap<ServerId, SharedBox<GattDatabase>>, 44 transport: Rc<dyn AttTransport>, 45 } 46 47 struct GattConnection { 48 bearer: SharedBox<AttServerBearer<AttDatabaseImpl>>, 49 database: WeakBox<GattDatabase>, 50 } 51 52 impl GattModule { 53 /// Constructor. new(transport: Rc<dyn AttTransport>) -> Self54 pub fn new(transport: Rc<dyn AttTransport>) -> Self { 55 Self { connections: HashMap::new(), databases: HashMap::new(), transport } 56 } 57 58 /// Handle LE link connect on_le_connect(&mut self, conn_id: ConnectionId) -> Result<()>59 pub fn on_le_connect(&mut self, conn_id: ConnectionId) -> Result<()> { 60 info!("connected on conn_id {conn_id:?}"); 61 let database = self.databases.get(&conn_id.get_server_id()); 62 let Some(database) = database else { 63 bail!( 64 "got connection to conn_id {conn_id:?} (server_id {:?}) but this server does not exist!", 65 conn_id.get_server_id(), 66 ); 67 }; 68 69 // TODO(aryarahul): do not pass in conn_id at all, derive it using the IsolationManager instead 70 let tcb_idx = conn_id.get_tcb_idx(); 71 72 let transport = self.transport.clone(); 73 let bearer = SharedBox::new(AttServerBearer::new( 74 database.get_att_database(tcb_idx), 75 move |packet| transport.send_packet(tcb_idx, packet), 76 )); 77 database.on_bearer_ready(tcb_idx, bearer.as_ref()); 78 self.connections.insert(tcb_idx, GattConnection { bearer, database: database.downgrade() }); 79 Ok(()) 80 } 81 82 /// Handle an LE link disconnect on_le_disconnect(&mut self, tcb_idx: TransportIndex) -> Result<()>83 pub fn on_le_disconnect(&mut self, tcb_idx: TransportIndex) -> Result<()> { 84 info!("disconnected conn_id {tcb_idx:?}"); 85 let connection = self.connections.remove(&tcb_idx); 86 let Some(connection) = connection else { 87 bail!("got disconnection from {tcb_idx:?} but bearer does not exist"); 88 }; 89 drop(connection.bearer); 90 connection.database.with(|db| db.map(|db| db.on_bearer_dropped(tcb_idx))); 91 Ok(()) 92 } 93 94 /// Register a new GATT service on a given server register_gatt_service( &mut self, server_id: ServerId, service: GattServiceWithHandle, datastore: impl RawGattDatastore + 'static, ) -> Result<()>95 pub fn register_gatt_service( 96 &mut self, 97 server_id: ServerId, 98 service: GattServiceWithHandle, 99 datastore: impl RawGattDatastore + 'static, 100 ) -> Result<()> { 101 self.databases 102 .get(&server_id) 103 .ok_or_else(|| anyhow!("server {server_id:?} not opened"))? 104 .add_service_with_handles(service, Rc::new(datastore)) 105 } 106 107 /// Unregister an existing GATT service on a given server unregister_gatt_service( &mut self, server_id: ServerId, service_handle: AttHandle, ) -> Result<()>108 pub fn unregister_gatt_service( 109 &mut self, 110 server_id: ServerId, 111 service_handle: AttHandle, 112 ) -> Result<()> { 113 self.databases 114 .get(&server_id) 115 .ok_or_else(|| anyhow!("server {server_id:?} not opened"))? 116 .remove_service_at_handle(service_handle) 117 } 118 119 /// Open a GATT server open_gatt_server(&mut self, server_id: ServerId) -> Result<()>120 pub fn open_gatt_server(&mut self, server_id: ServerId) -> Result<()> { 121 let mut db = GattDatabase::new(); 122 register_builtin_services(&mut db)?; 123 let old = self.databases.insert(server_id, db.into()); 124 if old.is_some() { 125 bail!("GATT server {server_id:?} already exists but was re-opened, clobbering old value...") 126 } 127 Ok(()) 128 } 129 130 /// Close a GATT server close_gatt_server(&mut self, server_id: ServerId) -> Result<()>131 pub fn close_gatt_server(&mut self, server_id: ServerId) -> Result<()> { 132 let old = self.databases.remove(&server_id); 133 if old.is_none() { 134 bail!("GATT server {server_id:?} did not exist") 135 }; 136 137 Ok(()) 138 } 139 140 /// Get an ATT bearer for a particular connection get_bearer( &self, tcb_idx: TransportIndex, ) -> Option<WeakBoxRef<AttServerBearer<AttDatabaseImpl>>>141 pub fn get_bearer( 142 &self, 143 tcb_idx: TransportIndex, 144 ) -> Option<WeakBoxRef<AttServerBearer<AttDatabaseImpl>>> { 145 self.connections.get(&tcb_idx).map(|x| x.bearer.as_ref()) 146 } 147 } 148