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