• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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