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