diff options
author | 2023-05-08 17:42:23 +0000 | |
---|---|---|
committer | 2023-05-08 20:31:42 +0000 | |
commit | c0c40140e83d449f254e8a0a20e61b6dfb580293 (patch) | |
tree | bb7229405ba67b431b97c5a1ccfeb99e8e31b4d4 | |
parent | 90fa684058835f926f8d755c4f311c131c7cfa43 (diff) |
[GATT Server] Use TransportIndex instead of conn_id in API
In preparation for supporting multiple GATT servers simultaneously, the
API of GattModule should use TransportIndex (i.e. connection handle),
rather than ConnectionId, since multiple ConnectionIds exist for a
single TransportIndex.
Test: unit
Bug: 274945531
Change-Id: Ie820bdab7a0d14b7f0aa6f2db37aa3bf568f4242
-rw-r--r-- | system/rust/build.rs | 4 | ||||
-rw-r--r-- | system/rust/src/gatt/arbiter.rs | 75 | ||||
-rw-r--r-- | system/rust/src/gatt/callbacks.rs | 52 | ||||
-rw-r--r-- | system/rust/src/gatt/callbacks/callback_transaction_manager.rs | 79 | ||||
-rw-r--r-- | system/rust/src/gatt/ffi.rs | 4 | ||||
-rw-r--r-- | system/rust/src/gatt/mocks/mock_database_callbacks.rs | 14 | ||||
-rw-r--r-- | system/rust/src/gatt/mocks/mock_datastore.rs | 14 | ||||
-rw-r--r-- | system/rust/src/gatt/mocks/mock_raw_datastore.rs | 26 | ||||
-rw-r--r-- | system/rust/src/gatt/server.rs | 38 | ||||
-rw-r--r-- | system/rust/src/gatt/server/att_server_bearer.rs | 8 | ||||
-rw-r--r-- | system/rust/src/gatt/server/gatt_database.rs | 98 | ||||
-rw-r--r-- | system/rust/src/gatt/server/services/gap.rs | 21 | ||||
-rw-r--r-- | system/rust/src/gatt/server/services/gatt.rs | 55 | ||||
-rw-r--r-- | system/rust/tests/gatt_callbacks_test.rs | 148 | ||||
-rw-r--r-- | system/rust/tests/gatt_server_test.rs | 50 |
15 files changed, 394 insertions, 292 deletions
diff --git a/system/rust/build.rs b/system/rust/build.rs index af1895276d..c4ccf5c05e 100644 --- a/system/rust/build.rs +++ b/system/rust/build.rs @@ -1,3 +1,7 @@ +//! Build file to generate packets +//! +//! Run `cargo install .` in `tools/pdl` to ensure `pdl` is in your +//! path. use std::{ env, fs::File, diff --git a/system/rust/src/gatt/arbiter.rs b/system/rust/src/gatt/arbiter.rs index 2db778589e..26a8d3319e 100644 --- a/system/rust/src/gatt/arbiter.rs +++ b/system/rust/src/gatt/arbiter.rs @@ -90,13 +90,15 @@ impl Arbiter { } /// Test to see if a buffer contains a valid ATT packet with an opcode we - /// are interested in intercepting (those intended for servers) + /// are interested in intercepting (those intended for servers that are isolated) pub fn try_parse_att_server_packet( &self, tcb_idx: TransportIndex, packet: Box<[u8]>, - ) -> Option<(OwnedAttView, ConnectionId)> { - let conn_id = *self.transport_to_owned_connection.get(&tcb_idx)?; + ) -> Option<OwnedAttView> { + if !self.transport_to_owned_connection.contains_key(&tcb_idx) { + return None; + } let att = OwnedAttView::try_parse(packet).ok()?; @@ -108,7 +110,7 @@ impl Arbiter { match classify_opcode(att.view().get_opcode()) { OperationType::Command | OperationType::Request | OperationType::Confirmation => { - Some((att, conn_id)) + Some(att) } _ => None, } @@ -135,10 +137,10 @@ impl Arbiter { Some(conn_id) } - /// Handle a disconnection and return the disconnected conn_id, if any - pub fn on_le_disconnect(&mut self, tcb_idx: TransportIndex) -> Option<ConnectionId> { + /// Handle a disconnection, if any, and return whether the disconnection was registered + pub fn on_le_disconnect(&mut self, tcb_idx: TransportIndex) -> bool { info!("processing disconnection on transport {tcb_idx:?}"); - self.transport_to_owned_connection.remove(&tcb_idx) + self.transport_to_owned_connection.remove(&tcb_idx).is_some() } /// Look up the conn_id for a given tcb_idx, if present @@ -160,10 +162,10 @@ fn on_le_connect(tcb_idx: u8, advertiser: u8) { } fn on_le_disconnect(tcb_idx: u8) { - if let Some(conn_id) = with_arbiter(|arbiter| arbiter.on_le_disconnect(TransportIndex(tcb_idx))) - { + let tcb_idx = TransportIndex(tcb_idx); + if with_arbiter(|arbiter| arbiter.on_le_disconnect(tcb_idx)) { do_in_rust_thread(move |modules| { - if let Err(err) = modules.gatt_module.on_le_disconnect(conn_id) { + if let Err(err) = modules.gatt_module.on_le_disconnect(tcb_idx) { error!("{err:?}") } }) @@ -171,15 +173,16 @@ fn on_le_disconnect(tcb_idx: u8) { } fn intercept_packet(tcb_idx: u8, packet: Vec<u8>) -> InterceptAction { - if let Some((att, conn_id)) = with_arbiter(|arbiter| { - arbiter.try_parse_att_server_packet(TransportIndex(tcb_idx), packet.into_boxed_slice()) + let tcb_idx = TransportIndex(tcb_idx); + if let Some(att) = with_arbiter(|arbiter| { + arbiter.try_parse_att_server_packet(tcb_idx, packet.into_boxed_slice()) }) { do_in_rust_thread(move |modules| { trace!("pushing packet to GATT"); - if let Some(bearer) = modules.gatt_module.get_bearer(conn_id) { + if let Some(bearer) = modules.gatt_module.get_bearer(tcb_idx) { bearer.handle_packet(att.view()) } else { - error!("{conn_id:?} closed, bearer does not exist"); + error!("Bearer for {tcb_idx:?} not found"); } }); InterceptAction::Drop @@ -189,10 +192,10 @@ fn intercept_packet(tcb_idx: u8, packet: Vec<u8>) -> InterceptAction { } fn on_mtu_event(tcb_idx: TransportIndex, event: MtuEvent) { - if let Some(conn_id) = with_arbiter(|arbiter| arbiter.get_conn_id(tcb_idx)) { + if with_arbiter(|arbiter| arbiter.get_conn_id(tcb_idx)).is_some() { do_in_rust_thread(move |modules| { - let Some(bearer) = modules.gatt_module.get_bearer(conn_id) else { - error!("Bearer for {conn_id:?} not found"); + let Some(bearer) = modules.gatt_module.get_bearer(tcb_idx) else { + error!("Bearer for {tcb_idx:?} not found"); return; }; if let Err(err) = bearer.handle_mtu_event(event) { @@ -215,12 +218,13 @@ mod test { }; const TCB_IDX: TransportIndex = TransportIndex(1); - const ADVERTISER_ID: AdvertiserId = AdvertiserId(2); - const SERVER_ID: ServerId = ServerId(3); + const ANOTHER_TCB_IDX: TransportIndex = TransportIndex(2); + const ADVERTISER_ID: AdvertiserId = AdvertiserId(3); + const SERVER_ID: ServerId = ServerId(4); const CONN_ID: ConnectionId = ConnectionId::new(TCB_IDX, SERVER_ID); - const ANOTHER_ADVERTISER_ID: AdvertiserId = AdvertiserId(4); + const ANOTHER_ADVERTISER_ID: AdvertiserId = AdvertiserId(5); #[test] fn test_non_isolated_connect() { @@ -256,9 +260,9 @@ mod test { let mut arbiter = Arbiter::new(); arbiter.on_le_connect(TCB_IDX, ADVERTISER_ID); - let conn_id = arbiter.on_le_disconnect(TCB_IDX); + let ok = arbiter.on_le_disconnect(TCB_IDX); - assert!(conn_id.is_none()) + assert!(!ok) } #[test] @@ -267,9 +271,9 @@ mod test { arbiter.associate_server_with_advertiser(SERVER_ID, ADVERTISER_ID); arbiter.on_le_connect(TCB_IDX, ADVERTISER_ID); - let conn_id = arbiter.on_le_disconnect(TCB_IDX); + let ok = arbiter.on_le_disconnect(TCB_IDX); - assert_eq!(conn_id, Some(CONN_ID)); + assert!(ok) } #[test] @@ -348,7 +352,7 @@ mod test { let out = arbiter.try_parse_att_server_packet(TCB_IDX, packet.to_vec().unwrap().into()); - assert!(matches!(out, Some((_, CONN_ID)))); + assert!(out.is_some()); } #[test] @@ -397,6 +401,23 @@ mod test { } #[test] + fn test_packet_bypass_when_different_connection() { + let mut arbiter = Arbiter::new(); + arbiter.associate_server_with_advertiser(SERVER_ID, ADVERTISER_ID); + arbiter.on_le_connect(TCB_IDX, ADVERTISER_ID); + arbiter.on_le_connect(ANOTHER_TCB_IDX, ANOTHER_ADVERTISER_ID); + let packet = AttBuilder { + opcode: AttOpcode::READ_REQUEST, + _child_: AttReadRequestBuilder { attribute_handle: AttHandle(1).into() }.into(), + }; + + let out = + arbiter.try_parse_att_server_packet(ANOTHER_TCB_IDX, packet.to_vec().unwrap().into()); + + assert!(out.is_none()); + } + + #[test] fn test_packet_capture_when_isolated_after_advertiser_closes() { let mut arbiter = Arbiter::new(); arbiter.associate_server_with_advertiser(SERVER_ID, ADVERTISER_ID); @@ -409,7 +430,7 @@ mod test { let out = arbiter.try_parse_att_server_packet(TCB_IDX, packet.to_vec().unwrap().into()); - assert!(matches!(out, Some((_, CONN_ID)))); + assert!(out.is_some()); } #[test] @@ -425,7 +446,7 @@ mod test { let out = arbiter.try_parse_att_server_packet(TCB_IDX, packet.to_vec().unwrap().into()); - assert!(matches!(out, Some((_, CONN_ID)))); + assert!(out.is_some()); } #[test] diff --git a/system/rust/src/gatt/callbacks.rs b/system/rust/src/gatt/callbacks.rs index 3f342d1626..f8958d7e05 100644 --- a/system/rust/src/gatt/callbacks.rs +++ b/system/rust/src/gatt/callbacks.rs @@ -13,7 +13,7 @@ use crate::packets::{AttAttributeDataChild, AttAttributeDataView, AttErrorCode}; use super::{ ffi::AttributeBackingType, - ids::{AttHandle, ConnectionId, TransactionId}, + ids::{AttHandle, ConnectionId, TransactionId, TransportIndex}, server::IndicationError, }; @@ -98,7 +98,7 @@ pub trait RawGattDatastore { /// Read a characteristic from the specified connection at the given handle. async fn read( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, offset: u32, attr_type: AttributeBackingType, @@ -107,7 +107,7 @@ pub trait RawGattDatastore { /// Write data to a given characteristic on the specified connection. async fn write( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, @@ -118,7 +118,7 @@ pub trait RawGattDatastore { /// for a response from the upper layer. fn write_no_response( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, data: AttAttributeDataView<'_>, @@ -127,7 +127,7 @@ pub trait RawGattDatastore { /// Execute or cancel any prepared writes async fn execute( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, decision: TransactionDecision, ) -> Result<(), AttErrorCode>; } @@ -139,7 +139,7 @@ pub trait GattDatastore { /// Read a characteristic from the specified connection at the given handle. async fn read( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, ) -> Result<AttAttributeDataChild, AttErrorCode>; @@ -147,7 +147,7 @@ pub trait GattDatastore { /// Write data to a given characteristic on the specified connection. async fn write( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, data: AttAttributeDataView<'_>, @@ -159,7 +159,7 @@ impl<T: GattDatastore + ?Sized> RawGattDatastore for T { /// Read a characteristic from the specified connection at the given handle. async fn read( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, offset: u32, attr_type: AttributeBackingType, @@ -168,13 +168,13 @@ impl<T: GattDatastore + ?Sized> RawGattDatastore for T { warn!("got read blob request for non-long attribute {handle:?}"); return Err(AttErrorCode::ATTRIBUTE_NOT_LONG); } - self.read(conn_id, handle, attr_type).await + self.read(tcb_idx, handle, attr_type).await } /// Write data to a given characteristic on the specified connection. async fn write( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, @@ -182,26 +182,26 @@ impl<T: GattDatastore + ?Sized> RawGattDatastore for T { ) -> Result<(), AttErrorCode> { match write_type { GattWriteRequestType::Prepare { .. } => { - warn!("got prepare write attempt to characteristic {handle:?} not supporting write_without_response"); + warn!("got prepare write attempt on {tcb_idx:?} to characteristic {handle:?} not supporting write_without_response"); Err(AttErrorCode::WRITE_REQUEST_REJECTED) } - GattWriteRequestType::Request => self.write(conn_id, handle, attr_type, data).await, + GattWriteRequestType::Request => self.write(tcb_idx, handle, attr_type, data).await, } } fn write_no_response( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, _: AttributeBackingType, _: AttAttributeDataView<'_>, ) { // silently drop, since there's no way to return an error - warn!("got write command on {conn_id:?} to characteristic {handle:?} not supporting write_without_response"); + warn!("got write command on {tcb_idx:?} to characteristic {handle:?} not supporting write_without_response"); } /// Execute or cancel any prepared writes - async fn execute(&self, _: ConnectionId, _: TransactionDecision) -> Result<(), AttErrorCode> { + async fn execute(&self, _: TransportIndex, _: TransactionDecision) -> Result<(), AttErrorCode> { // we never do prepared writes, so who cares return Ok(()); } @@ -222,7 +222,7 @@ mod test { use super::*; - const CONN_ID: ConnectionId = ConnectionId(1); + const TCB_IDX: TransportIndex = TransportIndex(1); const HANDLE: AttHandle = AttHandle(1); const DATA: [u8; 4] = [1, 2, 3, 4]; @@ -236,7 +236,7 @@ mod test { spawn_local(async move { RawGattDatastore::read( &datastore, - CONN_ID, + TCB_IDX, HANDLE, 0, AttributeBackingType::Characteristic, @@ -248,7 +248,7 @@ mod test { // assert: got read event assert!(matches!( resp, - MockDatastoreEvents::Read(CONN_ID, HANDLE, AttributeBackingType::Characteristic, _) + MockDatastoreEvents::Read(TCB_IDX, HANDLE, AttributeBackingType::Characteristic, _) )); }); } @@ -263,7 +263,7 @@ mod test { let pending = spawn_local(async move { RawGattDatastore::read( &datastore, - CONN_ID, + TCB_IDX, HANDLE, 0, AttributeBackingType::Characteristic, @@ -289,7 +289,7 @@ mod test { // act: send read blob request let resp = block_on_locally(RawGattDatastore::read( &datastore, - CONN_ID, + TCB_IDX, HANDLE, 1, AttributeBackingType::Characteristic, @@ -315,7 +315,7 @@ mod test { spawn_local(async move { RawGattDatastore::write( &datastore, - CONN_ID, + TCB_IDX, HANDLE, AttributeBackingType::Characteristic, GattWriteRequestType::Request, @@ -329,7 +329,7 @@ mod test { assert!(matches!( resp, MockDatastoreEvents::Write( - CONN_ID, + TCB_IDX, HANDLE, AttributeBackingType::Characteristic, _, @@ -349,7 +349,7 @@ mod test { let pending = spawn_local(async move { RawGattDatastore::write( &datastore, - CONN_ID, + TCB_IDX, HANDLE, AttributeBackingType::Characteristic, GattWriteRequestType::Request, @@ -376,7 +376,7 @@ mod test { // act: send prepare write request let resp = block_on_locally(RawGattDatastore::write( &datastore, - CONN_ID, + TCB_IDX, HANDLE, AttributeBackingType::Characteristic, GattWriteRequestType::Prepare { offset: 1 }, @@ -397,7 +397,7 @@ mod test { // act: send write command RawGattDatastore::write_no_response( &datastore, - CONN_ID, + TCB_IDX, HANDLE, AttributeBackingType::Characteristic, make_data().view(), @@ -415,7 +415,7 @@ mod test { // act: send execute request let resp = block_on_locally(RawGattDatastore::execute( &datastore, - CONN_ID, + TCB_IDX, TransactionDecision::Execute, )); diff --git a/system/rust/src/gatt/callbacks/callback_transaction_manager.rs b/system/rust/src/gatt/callbacks/callback_transaction_manager.rs index 153a1f2c20..c9c9862c81 100644 --- a/system/rust/src/gatt/callbacks/callback_transaction_manager.rs +++ b/system/rust/src/gatt/callbacks/callback_transaction_manager.rs @@ -6,7 +6,7 @@ use tokio::{sync::oneshot, time::timeout}; use crate::{ gatt::{ - ids::{AttHandle, ConnectionId, TransactionId}, + ids::{AttHandle, ConnectionId, ServerId, TransactionId, TransportIndex}, GattCallbacks, }, packets::{AttAttributeDataChild, AttAttributeDataView, AttErrorCode}, @@ -48,7 +48,7 @@ const TIMEOUT: Duration = Duration::from_secs(15); /// The cause of a failure to dispatch a call to send_response() #[derive(Debug, PartialEq, Eq)] pub enum CallbackResponseError { - /// The TransactionId supplied was invalid + /// The TransactionId supplied was invalid for the specified connection NonExistentTransaction(TransactionId), /// The TransactionId was valid but has since terminated ListenerHungUp(TransactionId), @@ -86,6 +86,11 @@ impl CallbackTransactionManager { Err(CallbackResponseError::NonExistentTransaction(trans_id)) } } + + /// Get an impl GattDatastore tied to a particular server + pub fn get_datastore(self: &Rc<Self>, server_id: ServerId) -> impl RawGattDatastore { + GattDatastoreImpl { callback_transaction_manager: self.clone(), server_id } + } } impl PendingTransactionsState { @@ -124,37 +129,58 @@ impl PendingTransactionWatcher { } } +struct GattDatastoreImpl { + callback_transaction_manager: Rc<CallbackTransactionManager>, + server_id: ServerId, +} + #[async_trait(?Send)] -impl RawGattDatastore for CallbackTransactionManager { +impl RawGattDatastore for GattDatastoreImpl { async fn read( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, offset: u32, attr_type: AttributeBackingType, ) -> Result<AttAttributeDataChild, AttErrorCode> { - let pending_transaction = - self.pending_transactions.borrow_mut().start_new_transaction(conn_id); + let conn_id = ConnectionId::new(tcb_idx, self.server_id); + + let pending_transaction = self + .callback_transaction_manager + .pending_transactions + .borrow_mut() + .start_new_transaction(conn_id); let trans_id = pending_transaction.trans_id; - self.callbacks.on_server_read(conn_id, trans_id, handle, attr_type, offset); + self.callback_transaction_manager.callbacks.on_server_read( + ConnectionId::new(tcb_idx, self.server_id), + trans_id, + handle, + attr_type, + offset, + ); - pending_transaction.wait(self).await + pending_transaction.wait(&self.callback_transaction_manager).await } async fn write( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, data: AttAttributeDataView<'_>, ) -> Result<(), AttErrorCode> { - let pending_transaction = - self.pending_transactions.borrow_mut().start_new_transaction(conn_id); + let conn_id = ConnectionId::new(tcb_idx, self.server_id); + + let pending_transaction = self + .callback_transaction_manager + .pending_transactions + .borrow_mut() + .start_new_transaction(conn_id); let trans_id = pending_transaction.trans_id; - self.callbacks.on_server_write( + self.callback_transaction_manager.callbacks.on_server_write( conn_id, trans_id, handle, @@ -164,18 +190,24 @@ impl RawGattDatastore for CallbackTransactionManager { ); // the data passed back is irrelevant for write requests - pending_transaction.wait(self).await.map(|_| ()) + pending_transaction.wait(&self.callback_transaction_manager).await.map(|_| ()) } fn write_no_response( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, data: AttAttributeDataView<'_>, ) { - let trans_id = self.pending_transactions.borrow_mut().alloc_transaction_id(); - self.callbacks.on_server_write( + let conn_id = ConnectionId::new(tcb_idx, self.server_id); + + let trans_id = self + .callback_transaction_manager + .pending_transactions + .borrow_mut() + .alloc_transaction_id(); + self.callback_transaction_manager.callbacks.on_server_write( conn_id, trans_id, handle, @@ -187,16 +219,21 @@ impl RawGattDatastore for CallbackTransactionManager { async fn execute( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, decision: TransactionDecision, ) -> Result<(), AttErrorCode> { - let pending_transaction = - self.pending_transactions.borrow_mut().start_new_transaction(conn_id); + let conn_id = ConnectionId::new(tcb_idx, self.server_id); + + let pending_transaction = self + .callback_transaction_manager + .pending_transactions + .borrow_mut() + .start_new_transaction(conn_id); let trans_id = pending_transaction.trans_id; - self.callbacks.on_execute(conn_id, trans_id, decision); + self.callback_transaction_manager.callbacks.on_execute(conn_id, trans_id, decision); // the data passed back is irrelevant for execute requests - pending_transaction.wait(self).await.map(|_| ()) + pending_transaction.wait(&self.callback_transaction_manager).await.map(|_| ()) } } diff --git a/system/rust/src/gatt/ffi.rs b/system/rust/src/gatt/ffi.rs index cae198dd05..8f86efe4ca 100644 --- a/system/rust/src/gatt/ffi.rs +++ b/system/rust/src/gatt/ffi.rs @@ -392,7 +392,7 @@ fn add_service(server_id: u8, service_records: Vec<GattRecord>) { let ok = modules.gatt_module.register_gatt_service( server_id, service.clone(), - modules.gatt_incoming_callbacks.clone(), + modules.gatt_incoming_callbacks.get_datastore(server_id), ); match ok { Ok(_) => info!( @@ -477,7 +477,7 @@ fn send_indication(_server_id: u8, handle: u16, conn_id: u16, value: &[u8]) { trace!("send_indication {handle:?}, {conn_id:?}"); do_in_rust_thread(move |modules| { - let Some(bearer) = modules.gatt_module.get_bearer(conn_id) else { + let Some(bearer) = modules.gatt_module.get_bearer(conn_id.get_tcb_idx()) else { error!("connection {conn_id:?} does not exist"); return; }; diff --git a/system/rust/src/gatt/mocks/mock_database_callbacks.rs b/system/rust/src/gatt/mocks/mock_database_callbacks.rs index bdcc335c0c..991b2f5f04 100644 --- a/system/rust/src/gatt/mocks/mock_database_callbacks.rs +++ b/system/rust/src/gatt/mocks/mock_database_callbacks.rs @@ -5,7 +5,7 @@ use std::ops::RangeInclusive; use crate::{ core::shared_box::{WeakBox, WeakBoxRef}, gatt::{ - ids::{AttHandle, ConnectionId}, + ids::{AttHandle, TransportIndex}, server::{ att_server_bearer::AttServerBearer, gatt_database::{AttDatabaseImpl, GattDatabaseCallbacks}, @@ -28,9 +28,9 @@ impl MockCallbacks { /// Events representing calls to GattCallbacks pub enum MockCallbackEvents { /// GattDatabaseCallbacks#on_le_connect invoked - OnLeConnect(ConnectionId, WeakBox<AttServerBearer<AttDatabaseImpl>>), + OnLeConnect(TransportIndex, WeakBox<AttServerBearer<AttDatabaseImpl>>), /// GattDatabaseCallbacks#on_le_disconnect invoked - OnLeDisconnect(ConnectionId), + OnLeDisconnect(TransportIndex), /// GattDatabaseCallbacks#on_service_change invoked OnServiceChange(RangeInclusive<AttHandle>), } @@ -38,14 +38,14 @@ pub enum MockCallbackEvents { impl GattDatabaseCallbacks for MockCallbacks { fn on_le_connect( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, bearer: WeakBoxRef<AttServerBearer<AttDatabaseImpl>>, ) { - self.0.send(MockCallbackEvents::OnLeConnect(conn_id, bearer.downgrade())).ok().unwrap(); + self.0.send(MockCallbackEvents::OnLeConnect(tcb_idx, bearer.downgrade())).ok().unwrap(); } - fn on_le_disconnect(&self, conn_id: ConnectionId) { - self.0.send(MockCallbackEvents::OnLeDisconnect(conn_id)).ok().unwrap(); + fn on_le_disconnect(&self, tcb_idx: TransportIndex) { + self.0.send(MockCallbackEvents::OnLeDisconnect(tcb_idx)).ok().unwrap(); } fn on_service_change(&self, range: RangeInclusive<AttHandle>) { diff --git a/system/rust/src/gatt/mocks/mock_datastore.rs b/system/rust/src/gatt/mocks/mock_datastore.rs index 130bcc0648..e21889421f 100644 --- a/system/rust/src/gatt/mocks/mock_datastore.rs +++ b/system/rust/src/gatt/mocks/mock_datastore.rs @@ -4,7 +4,7 @@ use crate::{ gatt::{ callbacks::GattDatastore, ffi::AttributeBackingType, - ids::{AttHandle, ConnectionId}, + ids::{AttHandle, TransportIndex}, }, packets::{ AttAttributeDataChild, AttAttributeDataView, AttErrorCode, OwnedAttAttributeDataView, @@ -35,7 +35,7 @@ pub enum MockDatastoreEvents { /// A characteristic was read on a given handle. The oneshot is used to /// return the value read. Read( - ConnectionId, + TransportIndex, AttHandle, AttributeBackingType, oneshot::Sender<Result<AttAttributeDataChild, AttErrorCode>>, @@ -43,7 +43,7 @@ pub enum MockDatastoreEvents { /// A characteristic was written to on a given handle. The oneshot is used /// to return whether the write succeeded. Write( - ConnectionId, + TransportIndex, AttHandle, AttributeBackingType, OwnedAttAttributeDataView, @@ -55,12 +55,12 @@ pub enum MockDatastoreEvents { impl GattDatastore for MockDatastore { async fn read( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, ) -> Result<AttAttributeDataChild, AttErrorCode> { let (tx, rx) = oneshot::channel(); - self.0.send(MockDatastoreEvents::Read(conn_id, handle, attr_type, tx)).unwrap(); + self.0.send(MockDatastoreEvents::Read(tcb_idx, handle, attr_type, tx)).unwrap(); let resp = rx.await.unwrap(); info!("sending {resp:?} down from upper tester"); resp @@ -68,7 +68,7 @@ impl GattDatastore for MockDatastore { async fn write( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, data: AttAttributeDataView<'_>, @@ -76,7 +76,7 @@ impl GattDatastore for MockDatastore { let (tx, rx) = oneshot::channel(); self.0 .send(MockDatastoreEvents::Write( - conn_id, + tcb_idx, handle, attr_type, data.to_owned_packet(), diff --git a/system/rust/src/gatt/mocks/mock_raw_datastore.rs b/system/rust/src/gatt/mocks/mock_raw_datastore.rs index 28aeac4131..7d4055ca2e 100644 --- a/system/rust/src/gatt/mocks/mock_raw_datastore.rs +++ b/system/rust/src/gatt/mocks/mock_raw_datastore.rs @@ -4,7 +4,7 @@ use crate::{ gatt::{ callbacks::{GattWriteRequestType, RawGattDatastore, TransactionDecision}, ffi::AttributeBackingType, - ids::{AttHandle, ConnectionId}, + ids::{AttHandle, TransportIndex}, }, packets::{ AttAttributeDataChild, AttAttributeDataView, AttErrorCode, OwnedAttAttributeDataView, @@ -35,7 +35,7 @@ pub enum MockRawDatastoreEvents { /// A characteristic was read on a given handle. The oneshot is used to /// return the value read. Read( - ConnectionId, + TransportIndex, AttHandle, AttributeBackingType, u32, @@ -44,7 +44,7 @@ pub enum MockRawDatastoreEvents { /// A characteristic was written to on a given handle. The oneshot is used /// to return whether the write succeeded. Write( - ConnectionId, + TransportIndex, AttHandle, AttributeBackingType, GattWriteRequestType, @@ -52,23 +52,23 @@ pub enum MockRawDatastoreEvents { oneshot::Sender<Result<(), AttErrorCode>>, ), /// A characteristic was written to on a given handle, where the response was disregarded. - WriteNoResponse(ConnectionId, AttHandle, AttributeBackingType, OwnedAttAttributeDataView), + WriteNoResponse(TransportIndex, AttHandle, AttributeBackingType, OwnedAttAttributeDataView), /// The prepared writes have been committed / aborted. The oneshot is used /// to return whether this operation succeeded. - Execute(ConnectionId, TransactionDecision, oneshot::Sender<Result<(), AttErrorCode>>), + Execute(TransportIndex, TransactionDecision, oneshot::Sender<Result<(), AttErrorCode>>), } #[async_trait(?Send)] impl RawGattDatastore for MockRawDatastore { async fn read( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, offset: u32, attr_type: AttributeBackingType, ) -> Result<AttAttributeDataChild, AttErrorCode> { let (tx, rx) = oneshot::channel(); - self.0.send(MockRawDatastoreEvents::Read(conn_id, handle, attr_type, offset, tx)).unwrap(); + self.0.send(MockRawDatastoreEvents::Read(tcb_idx, handle, attr_type, offset, tx)).unwrap(); let resp = rx.await.unwrap(); info!("sending {resp:?} down from upper tester"); resp @@ -76,7 +76,7 @@ impl RawGattDatastore for MockRawDatastore { async fn write( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, @@ -85,7 +85,7 @@ impl RawGattDatastore for MockRawDatastore { let (tx, rx) = oneshot::channel(); self.0 .send(MockRawDatastoreEvents::Write( - conn_id, + tcb_idx, handle, attr_type, write_type, @@ -98,14 +98,14 @@ impl RawGattDatastore for MockRawDatastore { fn write_no_response( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, data: AttAttributeDataView<'_>, ) { self.0 .send(MockRawDatastoreEvents::WriteNoResponse( - conn_id, + tcb_idx, handle, attr_type, data.to_owned_packet(), @@ -115,11 +115,11 @@ impl RawGattDatastore for MockRawDatastore { async fn execute( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, decision: TransactionDecision, ) -> Result<(), AttErrorCode> { let (tx, rx) = oneshot::channel(); - self.0.send(MockRawDatastoreEvents::Execute(conn_id, decision, tx)).unwrap(); + self.0.send(MockRawDatastoreEvents::Execute(tcb_idx, decision, tx)).unwrap(); rx.await.unwrap() } } diff --git a/system/rust/src/gatt/server.rs b/system/rust/src/gatt/server.rs index 2fd81cf2a6..09fd87964b 100644 --- a/system/rust/src/gatt/server.rs +++ b/system/rust/src/gatt/server.rs @@ -27,7 +27,11 @@ use self::{ services::register_builtin_services, }; -use super::{callbacks::RawGattDatastore, channel::AttTransport, ids::AttHandle}; +use super::{ + callbacks::RawGattDatastore, + channel::AttTransport, + ids::{AttHandle, TransportIndex}, +}; use anyhow::{anyhow, bail, Result}; use log::info; @@ -35,7 +39,7 @@ pub use indication_handler::IndicationError; #[allow(missing_docs)] pub struct GattModule { - connections: HashMap<ConnectionId, GattConnection>, + connections: HashMap<TransportIndex, GattConnection>, databases: HashMap<ServerId, SharedBox<GattDatabase>>, transport: Rc<dyn AttTransport>, } @@ -61,25 +65,29 @@ impl GattModule { conn_id.get_server_id(), ); }; + + // TODO(aryarahul): do not pass in conn_id at all, derive it using the IsolationManager instead + let tcb_idx = conn_id.get_tcb_idx(); + let transport = self.transport.clone(); let bearer = SharedBox::new(AttServerBearer::new( - database.get_att_database(conn_id), - move |packet| transport.send_packet(conn_id.get_tcb_idx(), packet), + database.get_att_database(tcb_idx), + move |packet| transport.send_packet(tcb_idx, packet), )); - database.on_bearer_ready(conn_id, bearer.as_ref()); - self.connections.insert(conn_id, GattConnection { bearer, database: database.downgrade() }); + database.on_bearer_ready(tcb_idx, bearer.as_ref()); + self.connections.insert(tcb_idx, GattConnection { bearer, database: database.downgrade() }); Ok(()) } /// Handle an LE link disconnect - pub fn on_le_disconnect(&mut self, conn_id: ConnectionId) -> Result<()> { - info!("disconnected conn_id {conn_id:?}"); - let connection = self.connections.remove(&conn_id); + pub fn on_le_disconnect(&mut self, tcb_idx: TransportIndex) -> Result<()> { + info!("disconnected conn_id {tcb_idx:?}"); + let connection = self.connections.remove(&tcb_idx); let Some(connection) = connection else { - bail!("got disconnection from {conn_id:?} but bearer does not exist"); + bail!("got disconnection from {tcb_idx:?} but bearer does not exist"); }; drop(connection.bearer); - connection.database.with(|db| db.map(|db| db.on_bearer_dropped(conn_id))); + connection.database.with(|db| db.map(|db| db.on_bearer_dropped(tcb_idx))); Ok(()) } @@ -88,12 +96,12 @@ impl GattModule { &mut self, server_id: ServerId, service: GattServiceWithHandle, - datastore: Rc<dyn RawGattDatastore>, + datastore: impl RawGattDatastore + 'static, ) -> Result<()> { self.databases .get(&server_id) .ok_or_else(|| anyhow!("server {server_id:?} not opened"))? - .add_service_with_handles(service, datastore) + .add_service_with_handles(service, Rc::new(datastore)) } /// Unregister an existing GATT service on a given server @@ -132,8 +140,8 @@ impl GattModule { /// Get an ATT bearer for a particular connection pub fn get_bearer( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, ) -> Option<WeakBoxRef<AttServerBearer<AttDatabaseImpl>>> { - self.connections.get(&conn_id).map(|x| x.bearer.as_ref()) + self.connections.get(&tcb_idx).map(|x| x.bearer.as_ref()) } } diff --git a/system/rust/src/gatt/server/att_server_bearer.rs b/system/rust/src/gatt/server/att_server_bearer.rs index d04ba66841..1c4a80e47f 100644 --- a/system/rust/src/gatt/server/att_server_bearer.rs +++ b/system/rust/src/gatt/server/att_server_bearer.rs @@ -223,7 +223,7 @@ mod test { core::{shared_box::SharedBox, uuid::Uuid}, gatt::{ ffi::AttributeBackingType, - ids::ConnectionId, + ids::TransportIndex, mocks::mock_datastore::{MockDatastore, MockDatastoreEvents}, server::{ att_database::{AttAttribute, AttPermissions}, @@ -247,7 +247,7 @@ mod test { const INVALID_HANDLE: AttHandle = AttHandle(4); const ANOTHER_VALID_HANDLE: AttHandle = AttHandle(10); - const CONN_ID: ConnectionId = ConnectionId(1); + const TCB_IDX: TransportIndex = TransportIndex(1); fn open_connection( ) -> (SharedBox<AttServerBearer<TestAttDatabase>>, UnboundedReceiver<AttBuilder>) { @@ -351,7 +351,7 @@ mod test { tx.send(packet).unwrap(); Ok(()) }; - let conn = SharedBox::new(AttServerBearer::new(db.get_att_database(CONN_ID), send_packet)); + let conn = SharedBox::new(AttServerBearer::new(db.get_att_database(TCB_IDX), send_packet)); let data = AttAttributeDataChild::RawData([1, 2].into()); // act: send two read requests before replying to either read @@ -367,7 +367,7 @@ mod test { }); conn.as_ref().handle_packet(req2.view()); // handle first reply - let MockDatastoreEvents::Read(CONN_ID, VALID_HANDLE, AttributeBackingType::Characteristic, data_resp) = + let MockDatastoreEvents::Read(TCB_IDX, VALID_HANDLE, AttributeBackingType::Characteristic, data_resp) = data_rx.recv().await.unwrap() else { unreachable!(); }; diff --git a/system/rust/src/gatt/server/gatt_database.rs b/system/rust/src/gatt/server/gatt_database.rs index 7702d22f77..00cda0df23 100644 --- a/system/rust/src/gatt/server/gatt_database.rs +++ b/system/rust/src/gatt/server/gatt_database.rs @@ -16,7 +16,7 @@ use crate::{ gatt::{ callbacks::{GattWriteRequestType, RawGattDatastore}, ffi::AttributeBackingType, - ids::{AttHandle, ConnectionId}, + ids::{AttHandle, TransportIndex}, }, packets::{ AttAttributeDataChild, AttAttributeDataView, AttErrorCode, @@ -120,11 +120,11 @@ pub trait GattDatabaseCallbacks { /// A peer device on the given bearer has connected to this database (and can see its attributes) fn on_le_connect( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, bearer: WeakBoxRef<AttServerBearer<AttDatabaseImpl>>, ); /// A peer device has disconnected from this database - fn on_le_disconnect(&self, conn_id: ConnectionId); + fn on_le_disconnect(&self, tcb_idx: TransportIndex); /// The attributes in the specified range have changed fn on_service_change(&self, range: RangeInclusive<AttHandle>); } @@ -144,18 +144,18 @@ impl GattDatabase { /// The supplied bearer is guaranteed to be ready for use. pub fn on_bearer_ready( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, bearer: WeakBoxRef<AttServerBearer<AttDatabaseImpl>>, ) { for listener in self.listeners.borrow().iter() { - listener.on_le_connect(conn_id, bearer.clone()); + listener.on_le_connect(tcb_idx, bearer.clone()); } } /// When the connection has dropped. - pub fn on_bearer_dropped(&self, conn_id: ConnectionId) { + pub fn on_bearer_dropped(&self, tcb_idx: TransportIndex) { for listener in self.listeners.borrow().iter() { - listener.on_le_disconnect(conn_id); + listener.on_le_disconnect(tcb_idx); } } @@ -328,15 +328,15 @@ impl SharedBox<GattDatabase> { /// /// Note: After the AttDatabaseImpl is constructed, we MUST call on_bearer_ready() with /// the resultant bearer, so that the listeners get the correct sequence of callbacks. - pub fn get_att_database(&self, conn_id: ConnectionId) -> AttDatabaseImpl { - AttDatabaseImpl { gatt_db: self.downgrade(), conn_id } + pub fn get_att_database(&self, tcb_idx: TransportIndex) -> AttDatabaseImpl { + AttDatabaseImpl { gatt_db: self.downgrade(), tcb_idx } } } /// An implementation of AttDatabase wrapping an underlying GattDatabase pub struct AttDatabaseImpl { gatt_db: WeakBox<GattDatabase>, - conn_id: ConnectionId, + tcb_idx: TransportIndex, } #[async_trait(?Send)] @@ -365,7 +365,7 @@ impl AttDatabase for AttDatabaseImpl { AttAttributeBackingValue::DynamicCharacteristic(datastore) => { datastore .read( - self.conn_id, + self.tcb_idx, handle, /* offset */ 0, AttributeBackingType::Characteristic, @@ -375,7 +375,7 @@ impl AttDatabase for AttDatabaseImpl { AttAttributeBackingValue::DynamicDescriptor(datastore) => { datastore .read( - self.conn_id, + self.tcb_idx, handle, /* offset */ 0, AttributeBackingType::Descriptor, @@ -413,7 +413,7 @@ impl AttDatabase for AttDatabaseImpl { AttAttributeBackingValue::DynamicCharacteristic(datastore) => { datastore .write( - self.conn_id, + self.tcb_idx, handle, AttributeBackingType::Characteristic, GattWriteRequestType::Request, @@ -424,7 +424,7 @@ impl AttDatabase for AttDatabaseImpl { AttAttributeBackingValue::DynamicDescriptor(datastore) => { datastore .write( - self.conn_id, + self.tcb_idx, handle, AttributeBackingType::Descriptor, GattWriteRequestType::Request, @@ -463,7 +463,7 @@ impl AttDatabase for AttDatabaseImpl { } AttAttributeBackingValue::DynamicCharacteristic(datastore) => { datastore.write_no_response( - self.conn_id, + self.tcb_idx, handle, AttributeBackingType::Characteristic, data, @@ -471,7 +471,7 @@ impl AttDatabase for AttDatabaseImpl { } AttAttributeBackingValue::DynamicDescriptor(datastore) => { datastore.write_no_response( - self.conn_id, + self.tcb_idx, handle, AttributeBackingType::Descriptor, data, @@ -490,7 +490,7 @@ impl AttDatabase for AttDatabaseImpl { impl Clone for AttDatabaseImpl { fn clone(&self) -> Self { - Self { gatt_db: self.gatt_db.clone(), conn_id: self.conn_id } + Self { gatt_db: self.gatt_db.clone(), tcb_idx: self.tcb_idx } } } @@ -505,7 +505,7 @@ impl AttDatabaseImpl { self.gatt_db.with(|db| { db.map(|db| { for listener in db.listeners.borrow().iter() { - listener.on_le_disconnect(self.conn_id) + listener.on_le_disconnect(self.tcb_idx) } }) }); @@ -541,12 +541,12 @@ mod test { const DESCRIPTOR_HANDLE: AttHandle = AttHandle(4); const DESCRIPTOR_TYPE: Uuid = Uuid::new(0x9ABC); - const CONN_ID: ConnectionId = ConnectionId(1); + const TCB_IDX: TransportIndex = TransportIndex(1); #[test] fn test_read_empty_db() { let gatt_db = SharedBox::new(GattDatabase::new()); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let resp = tokio_test::block_on(att_db.read_attribute(AttHandle(1))); @@ -567,7 +567,7 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let attrs = att_db.list_attributes(); let service_value = tokio_test::block_on(att_db.read_attribute(SERVICE_HANDLE)); @@ -640,7 +640,7 @@ mod test { gatt_datastore, ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); assert_eq!(att_db.list_attributes().len(), 9); // act: remove the middle service @@ -690,7 +690,7 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let attrs = att_db.list_attributes(); let characteristic_decl = @@ -743,7 +743,7 @@ mod test { // arrange let (gatt_datastore, _) = MockDatastore::new(); let gatt_db = SharedBox::new(GattDatabase::new()); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); // act: add a characteristic with all permission bits set gatt_db @@ -806,7 +806,7 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let data = AttAttributeDataChild::RawData(Box::new([1, 2])); // act: read from the database, and supply a value from the backing datastore @@ -814,7 +814,7 @@ mod test { join!( async { let MockDatastoreEvents::Read( - CONN_ID, + TCB_IDX, CHARACTERISTIC_VALUE_HANDLE, AttributeBackingType::Characteristic, reply, @@ -853,7 +853,7 @@ mod test { .unwrap(); let characteristic_value = tokio_test::block_on( - gatt_db.get_att_database(CONN_ID).read_attribute(CHARACTERISTIC_VALUE_HANDLE), + gatt_db.get_att_database(TCB_IDX).read_attribute(CHARACTERISTIC_VALUE_HANDLE), ); assert_eq!(characteristic_value, Err(AttErrorCode::READ_NOT_PERMITTED)); @@ -930,7 +930,7 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let data = build_view_or_crash(build_att_data(AttAttributeDataChild::RawData(Box::new([1, 2])))); @@ -946,7 +946,7 @@ mod test { }); let MockDatastoreEvents::Write( - CONN_ID, + TCB_IDX, CHARACTERISTIC_VALUE_HANDLE, AttributeBackingType::Characteristic, recv_data, @@ -984,7 +984,7 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let data = build_view_or_crash(build_att_data(AttAttributeDataChild::RawData(Box::new([1, 2])))); @@ -1030,7 +1030,7 @@ mod test { let characteristic_value = tokio_test::block_on( gatt_db - .get_att_database(CONN_ID) + .get_att_database(TCB_IDX) .write_attribute(CHARACTERISTIC_VALUE_HANDLE, data.view()), ); @@ -1060,7 +1060,7 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let data = AttAttributeDataChild::RawData(Box::new([1, 2])); let descriptor_value = block_on_locally(async { @@ -1069,7 +1069,7 @@ mod test { spawn_local(async move { att_db.read_attribute(DESCRIPTOR_HANDLE).await.unwrap() }); let MockDatastoreEvents::Read( - CONN_ID, + TCB_IDX, DESCRIPTOR_HANDLE, AttributeBackingType::Descriptor, reply, @@ -1109,7 +1109,7 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let data = build_view_or_crash(build_att_data(AttAttributeDataChild::RawData(Box::new([1, 2])))); @@ -1121,7 +1121,7 @@ mod test { }); let MockDatastoreEvents::Write( - CONN_ID, + TCB_IDX, DESCRIPTOR_HANDLE, AttributeBackingType::Descriptor, _, @@ -1180,7 +1180,7 @@ mod test { .unwrap(); // act: get the attributes - let attributes = gatt_db.get_att_database(CONN_ID).list_attributes(); + let attributes = gatt_db.get_att_database(TCB_IDX).list_attributes(); // assert: check the attributes are in the correct order assert_eq!(attributes.len(), 8); @@ -1244,7 +1244,7 @@ mod test { ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let data = AttAttributeDataChild::RawData(Box::new([1, 2])); // act: read from the second characteristic and supply a response from the second datastore @@ -1252,7 +1252,7 @@ mod test { join!( async { let MockDatastoreEvents::Read( - CONN_ID, + TCB_IDX, AttHandle(6), AttributeBackingType::Characteristic, reply, @@ -1277,7 +1277,7 @@ mod test { fn make_bearer( gatt_db: &SharedBox<GattDatabase>, ) -> SharedBox<AttServerBearer<AttDatabaseImpl>> { - SharedBox::new(AttServerBearer::new(gatt_db.get_att_database(CONN_ID), |_| { + SharedBox::new(AttServerBearer::new(gatt_db.get_att_database(TCB_IDX), |_| { unreachable!(); })) } @@ -1291,11 +1291,11 @@ mod test { let bearer = make_bearer(&gatt_db); // act: open a connection - gatt_db.on_bearer_ready(CONN_ID, bearer.as_ref()); + gatt_db.on_bearer_ready(TCB_IDX, bearer.as_ref()); // assert: we got the callback let event = rx.blocking_recv().unwrap(); - assert!(matches!(event, MockCallbackEvents::OnLeConnect(CONN_ID, _))); + assert!(matches!(event, MockCallbackEvents::OnLeConnect(TCB_IDX, _))); } #[test] @@ -1306,11 +1306,11 @@ mod test { gatt_db.register_listener(Rc::new(callbacks)); // act: disconnect - gatt_db.on_bearer_dropped(CONN_ID); + gatt_db.on_bearer_dropped(TCB_IDX); // assert: we got the callback let event = rx.blocking_recv().unwrap(); - assert!(matches!(event, MockCallbackEvents::OnLeDisconnect(CONN_ID))); + assert!(matches!(event, MockCallbackEvents::OnLeDisconnect(TCB_IDX))); } #[test] @@ -1323,13 +1323,13 @@ mod test { gatt_db.register_listener(Rc::new(callbacks2)); // act: disconnect - gatt_db.on_bearer_dropped(CONN_ID); + gatt_db.on_bearer_dropped(TCB_IDX); // assert: we got the callback on both listeners let event = rx1.blocking_recv().unwrap(); - assert!(matches!(event, MockCallbackEvents::OnLeDisconnect(CONN_ID))); + assert!(matches!(event, MockCallbackEvents::OnLeDisconnect(TCB_IDX))); let event = rx2.blocking_recv().unwrap(); - assert!(matches!(event, MockCallbackEvents::OnLeDisconnect(CONN_ID))); + assert!(matches!(event, MockCallbackEvents::OnLeDisconnect(TCB_IDX))); } #[test] @@ -1502,7 +1502,7 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let data = build_view_or_crash(build_att_data(AttAttributeDataChild::RawData(Box::new([1, 2])))); @@ -1511,7 +1511,7 @@ mod test { // assert: we got a callback let event = data_evts.blocking_recv().unwrap(); - let MockRawDatastoreEvents::WriteNoResponse(CONN_ID, CHARACTERISTIC_VALUE_HANDLE, AttributeBackingType::Characteristic, recv_data) = event else { + let MockRawDatastoreEvents::WriteNoResponse(TCB_IDX, CHARACTERISTIC_VALUE_HANDLE, AttributeBackingType::Characteristic, recv_data) = event else { unreachable!("{event:?}"); }; assert_eq!( @@ -1541,7 +1541,7 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let att_db = gatt_db.get_att_database(CONN_ID); + let att_db = gatt_db.get_att_database(TCB_IDX); let data = build_view_or_crash(build_att_data(AttAttributeDataChild::RawData(Box::new([1, 2])))); diff --git a/system/rust/src/gatt/server/services/gap.rs b/system/rust/src/gatt/server/services/gap.rs index 44646d7cc9..c601587a18 100644 --- a/system/rust/src/gatt/server/services/gap.rs +++ b/system/rust/src/gatt/server/services/gap.rs @@ -10,7 +10,7 @@ use crate::{ gatt::{ callbacks::GattDatastore, ffi::AttributeBackingType, - ids::{AttHandle, ConnectionId}, + ids::{AttHandle, TransportIndex}, server::gatt_database::{ AttPermissions, GattCharacteristicWithHandle, GattDatabase, GattServiceWithHandle, }, @@ -36,7 +36,7 @@ pub const DEVICE_APPEARANCE_UUID: Uuid = Uuid::new(0x2A01); impl GattDatastore for GapService { async fn read( &self, - _: ConnectionId, + _: TransportIndex, handle: AttHandle, _: AttributeBackingType, ) -> Result<AttAttributeDataChild, AttErrorCode> { @@ -54,7 +54,7 @@ impl GattDatastore for GapService { async fn write( &self, - _: ConnectionId, + _: TransportIndex, _: AttHandle, _: AttributeBackingType, _: AttAttributeDataView<'_>, @@ -97,25 +97,20 @@ mod test { use crate::{ core::shared_box::SharedBox, - gatt::{ - ids::ConnectionId, - server::{ - att_database::AttDatabase, - gatt_database::{ - GattDatabase, CHARACTERISTIC_UUID, PRIMARY_SERVICE_DECLARATION_UUID, - }, - }, + gatt::server::{ + att_database::AttDatabase, + gatt_database::{GattDatabase, CHARACTERISTIC_UUID, PRIMARY_SERVICE_DECLARATION_UUID}, }, utils::task::block_on_locally, }; - const CONN_ID: ConnectionId = ConnectionId(1); + const TCB_IDX: TransportIndex = TransportIndex(1); fn init_dbs() -> (SharedBox<GattDatabase>, impl AttDatabase) { let mut gatt_database = GattDatabase::new(); register_gap_service(&mut gatt_database).unwrap(); let gatt_database = SharedBox::new(gatt_database); - let att_database = gatt_database.get_att_database(CONN_ID); + let att_database = gatt_database.get_att_database(TCB_IDX); (gatt_database, att_database) } diff --git a/system/rust/src/gatt/server/services/gatt.rs b/system/rust/src/gatt/server/services/gatt.rs index eb3ba477db..edd146d600 100644 --- a/system/rust/src/gatt/server/services/gatt.rs +++ b/system/rust/src/gatt/server/services/gatt.rs @@ -15,7 +15,7 @@ use crate::{ gatt::{ callbacks::GattDatastore, ffi::AttributeBackingType, - ids::{AttHandle, ConnectionId}, + ids::{AttHandle, TransportIndex}, server::{ att_server_bearer::AttServerBearer, gatt_database::{ @@ -33,7 +33,7 @@ use crate::{ #[derive(Default)] struct GattService { - clients: RefCell<HashMap<ConnectionId, ClientState>>, + clients: RefCell<HashMap<TransportIndex, ClientState>>, } #[derive(Clone)] @@ -58,7 +58,7 @@ pub const CLIENT_CHARACTERISTIC_CONFIGURATION_UUID: Uuid = Uuid::new(0x2902); impl GattDatastore for GattService { async fn read( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, _: AttributeBackingType, ) -> Result<AttAttributeDataChild, AttErrorCode> { @@ -68,7 +68,7 @@ impl GattDatastore for GattService { indication: self .clients .borrow() - .get(&conn_id) + .get(&tcb_idx) .map(|state| state.registered_for_service_change) .unwrap_or(false) .into(), @@ -81,7 +81,7 @@ impl GattDatastore for GattService { async fn write( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, handle: AttHandle, _: AttributeBackingType, data: AttAttributeDataView<'_>, @@ -93,7 +93,7 @@ impl GattDatastore for GattService { AttErrorCode::APPLICATION_ERROR })?; let mut clients = self.clients.borrow_mut(); - let state = clients.get_mut(&conn_id); + let state = clients.get_mut(&tcb_idx); let Some(mut state) = state else { error!("Received write request from disconnected client..."); return Err(AttErrorCode::UNLIKELY_ERROR); @@ -109,18 +109,18 @@ impl GattDatastore for GattService { impl GattDatabaseCallbacks for GattService { fn on_le_connect( &self, - conn_id: ConnectionId, + tcb_idx: TransportIndex, bearer: WeakBoxRef<AttServerBearer<AttDatabaseImpl>>, ) { // TODO(aryarahul): registered_for_service_change may not be false for bonded devices self.clients.borrow_mut().insert( - conn_id, + tcb_idx, ClientState { bearer: bearer.downgrade(), registered_for_service_change: false }, ); } - fn on_le_disconnect(&self, conn_id: ConnectionId) { - self.clients.borrow_mut().remove(&conn_id); + fn on_le_disconnect(&self, tcb_idx: TransportIndex) { + self.clients.borrow_mut().remove(&tcb_idx); } fn on_service_change(&self, range: RangeInclusive<AttHandle>) { @@ -182,7 +182,6 @@ mod test { use crate::{ core::shared_box::SharedBox, gatt::{ - ids::ConnectionId, mocks::mock_datastore::MockDatastore, server::{ att_database::AttDatabase, @@ -198,8 +197,8 @@ mod test { }, }; - const CONN_ID: ConnectionId = ConnectionId(1); - const ANOTHER_CONN_ID: ConnectionId = ConnectionId(2); + const TCB_IDX: TransportIndex = TransportIndex(1); + const ANOTHER_TCB_IDX: TransportIndex = TransportIndex(2); const SERVICE_TYPE: Uuid = Uuid::new(0x1234); const CHARACTERISTIC_TYPE: Uuid = Uuid::new(0x5678); @@ -211,16 +210,16 @@ mod test { fn add_connection( gatt_database: &SharedBox<GattDatabase>, - conn_id: ConnectionId, + tcb_idx: TransportIndex, ) -> (AttDatabaseImpl, SharedBox<AttServerBearer<AttDatabaseImpl>>, UnboundedReceiver<AttBuilder>) { - let att_database = gatt_database.get_att_database(conn_id); + let att_database = gatt_database.get_att_database(tcb_idx); let (tx, rx) = unbounded_channel(); let bearer = SharedBox::new(AttServerBearer::new(att_database.clone(), move |packet| { tx.send(packet).unwrap(); Ok(()) })); - gatt_database.on_bearer_ready(conn_id, bearer.as_ref()); + gatt_database.on_bearer_ready(tcb_idx, bearer.as_ref()); (att_database, bearer, rx) } @@ -228,7 +227,7 @@ mod test { fn test_gatt_service_discovery() { // arrange let gatt_db = init_gatt_db(); - let (att_db, _, _) = add_connection(&gatt_db, CONN_ID); + let (att_db, _, _) = add_connection(&gatt_db, TCB_IDX); // act: discover all services let attrs = att_db.list_attributes(); @@ -255,7 +254,7 @@ mod test { fn test_default_indication_subscription() { // arrange let gatt_db = init_gatt_db(); - let (att_db, _, _) = add_connection(&gatt_db, CONN_ID); + let (att_db, _, _) = add_connection(&gatt_db, TCB_IDX); // act: try to read the CCC descriptor let resp = @@ -291,7 +290,7 @@ mod test { fn test_subscribe_to_indication() { // arrange let gatt_db = init_gatt_db(); - let (att_db, _, _) = add_connection(&gatt_db, CONN_ID); + let (att_db, _, _) = add_connection(&gatt_db, TCB_IDX); // act: register for service change indication block_on_locally(register_for_indication(&att_db, SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE)) @@ -314,7 +313,7 @@ mod test { fn test_unsubscribe_to_indication() { // arrange let gatt_db = init_gatt_db(); - let (att_db, _, _) = add_connection(&gatt_db, CONN_ID); + let (att_db, _, _) = add_connection(&gatt_db, TCB_IDX); // act: register for service change indication block_on_locally( @@ -359,7 +358,7 @@ mod test { block_on_locally(async { // arrange let gatt_db = init_gatt_db(); - let (att_db, _bearer, mut rx) = add_connection(&gatt_db, CONN_ID); + let (att_db, _bearer, mut rx) = add_connection(&gatt_db, TCB_IDX); let (gatt_datastore, _) = MockDatastore::new(); let gatt_datastore = Rc::new(gatt_datastore); register_for_indication(&att_db, SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE).await.unwrap(); @@ -399,8 +398,8 @@ mod test { block_on_locally(async { // arrange: two connections, both registered let gatt_db = init_gatt_db(); - let (att_db_1, _bearer, mut rx1) = add_connection(&gatt_db, CONN_ID); - let (att_db_2, _bearer, mut rx2) = add_connection(&gatt_db, ANOTHER_CONN_ID); + let (att_db_1, _bearer, mut rx1) = add_connection(&gatt_db, TCB_IDX); + let (att_db_2, _bearer, mut rx2) = add_connection(&gatt_db, ANOTHER_TCB_IDX); register_for_indication(&att_db_1, SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE).await.unwrap(); register_for_indication(&att_db_2, SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE).await.unwrap(); @@ -438,8 +437,8 @@ mod test { block_on_locally(async { // arrange: two connections, only the first is registered let gatt_db = init_gatt_db(); - let (att_db_1, _bearer, mut rx1) = add_connection(&gatt_db, CONN_ID); - let (_, _bearer, mut rx2) = add_connection(&gatt_db, ANOTHER_CONN_ID); + let (att_db_1, _bearer, mut rx1) = add_connection(&gatt_db, TCB_IDX); + let (_, _bearer, mut rx2) = add_connection(&gatt_db, ANOTHER_TCB_IDX); register_for_indication(&att_db_1, SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE).await.unwrap(); @@ -476,14 +475,14 @@ mod test { block_on_locally(async { // arrange: two connections, both register, but the second one disconnects let gatt_db = init_gatt_db(); - let (att_db_1, _bearer, mut rx1) = add_connection(&gatt_db, CONN_ID); - let (att_db_2, bearer_2, mut rx2) = add_connection(&gatt_db, ANOTHER_CONN_ID); + let (att_db_1, _bearer, mut rx1) = add_connection(&gatt_db, TCB_IDX); + let (att_db_2, bearer_2, mut rx2) = add_connection(&gatt_db, ANOTHER_TCB_IDX); register_for_indication(&att_db_1, SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE).await.unwrap(); register_for_indication(&att_db_2, SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE).await.unwrap(); drop(bearer_2); - gatt_db.on_bearer_dropped(ANOTHER_CONN_ID); + gatt_db.on_bearer_dropped(ANOTHER_TCB_IDX); let (gatt_datastore, _) = MockDatastore::new(); let gatt_datastore = Rc::new(gatt_datastore); diff --git a/system/rust/tests/gatt_callbacks_test.rs b/system/rust/tests/gatt_callbacks_test.rs index 98b2838567..30a83fe21b 100644 --- a/system/rust/tests/gatt_callbacks_test.rs +++ b/system/rust/tests/gatt_callbacks_test.rs @@ -52,9 +52,12 @@ fn test_read_characteristic_callback() { let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); // act: start read operation - spawn_local( - async move { callback_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await }, - ); + spawn_local(async move { + callback_manager + .get_datastore(SERVER_ID) + .read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE) + .await + }); // assert: verify the read callback is received let MockCallbackEvents::OnServerRead( @@ -73,10 +76,11 @@ fn test_read_characteristic_response() { let data = Ok(AttAttributeDataChild::RawData([1, 2].into())); // act: start read operation - let cloned_manager = callback_manager.clone(); - let pending_read = spawn_local(async move { - cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await - }); + let datastore = callback_manager.get_datastore(SERVER_ID); + let pending_read = + spawn_local( + async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }, + ); // provide a response let trans_id = pull_trans_id(&mut callbacks_rx).await; callback_manager.send_response(CONN_ID, trans_id, data.clone()).unwrap(); @@ -95,19 +99,21 @@ fn test_sequential_reads() { let data2 = Ok(AttAttributeDataChild::RawData([3, 4].into())); // act: start read operation - let cloned_manager = callback_manager.clone(); - let pending_read_1 = spawn_local(async move { - cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await - }); + let datastore = callback_manager.get_datastore(SERVER_ID); + let pending_read_1 = + spawn_local( + async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }, + ); // respond to first let trans_id = pull_trans_id(&mut callbacks_rx).await; callback_manager.send_response(CONN_ID, trans_id, data1.clone()).unwrap(); // do a second read operation - let cloned_manager = callback_manager.clone(); - let pending_read_2 = spawn_local(async move { - cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await - }); + let datastore = callback_manager.get_datastore(SERVER_ID); + let pending_read_2 = + spawn_local( + async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }, + ); // respond to second let trans_id = pull_trans_id(&mut callbacks_rx).await; callback_manager.send_response(CONN_ID, trans_id, data2.clone()).unwrap(); @@ -127,16 +133,18 @@ fn test_concurrent_reads() { let data2 = Ok(AttAttributeDataChild::RawData([3, 4].into())); // act: start read operation - let cloned_manager = callback_manager.clone(); - let pending_read_1 = spawn_local(async move { - cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await - }); + let datastore = callback_manager.get_datastore(SERVER_ID); + let pending_read_1 = + spawn_local( + async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }, + ); // do a second read operation - let cloned_manager = callback_manager.clone(); - let pending_read_2 = spawn_local(async move { - cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await - }); + let datastore = callback_manager.get_datastore(SERVER_ID); + let pending_read_2 = + spawn_local( + async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }, + ); // respond to first let trans_id = pull_trans_id(&mut callbacks_rx).await; @@ -159,14 +167,10 @@ fn test_distinct_transaction_ids() { let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); // act: start two read operations concurrently - let cloned_manager = callback_manager.clone(); - spawn_local( - async move { cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await }, - ); - let cloned_manager = callback_manager.clone(); - spawn_local( - async move { cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await }, - ); + let datastore = callback_manager.get_datastore(SERVER_ID); + spawn_local(async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }); + let datastore = callback_manager.get_datastore(SERVER_ID); + spawn_local(async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }); // pull both trans_ids let trans_id_1 = pull_trans_id(&mut callbacks_rx).await; @@ -185,10 +189,8 @@ fn test_invalid_trans_id() { let data = Ok(AttAttributeDataChild::RawData([1, 2].into())); // act: start a read operation - let cloned_manager = callback_manager.clone(); - spawn_local( - async move { cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await }, - ); + let datastore = callback_manager.get_datastore(SERVER_ID); + spawn_local(async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }); // respond with the correct conn_id but an invalid trans_id let trans_id = pull_trans_id(&mut callbacks_rx).await; let invalid_trans_id = TransactionId(trans_id.0 + 1); @@ -200,6 +202,26 @@ fn test_invalid_trans_id() { } #[test] +fn test_invalid_conn_id() { + start_test(async { + // arrange + let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); + let data = Ok(AttAttributeDataChild::RawData([1, 2].into())); + + // act: start a read operation + let datastore = callback_manager.get_datastore(SERVER_ID); + spawn_local(async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }); + // respond with the correct trans_id but an invalid conn_id + let trans_id = pull_trans_id(&mut callbacks_rx).await; + let invalid_conn_id = ConnectionId(CONN_ID.0 + 1); + let err = callback_manager.send_response(invalid_conn_id, trans_id, data).unwrap_err(); + + // assert + assert_eq!(err, CallbackResponseError::NonExistentTransaction(trans_id)); + }); +} + +#[test] fn test_write_characteristic_callback() { start_test(async { // arrange @@ -211,7 +233,8 @@ fn test_write_characteristic_callback() { let cloned_data = data.view().to_owned_packet(); spawn_local(async move { callback_manager - .write(CONN_ID, HANDLE_1, BACKING_TYPE, WRITE_REQUEST_TYPE, cloned_data.view()) + .get_datastore(SERVER_ID) + .write(TCB_IDX, HANDLE_1, BACKING_TYPE, WRITE_REQUEST_TYPE, cloned_data.view()) .await }); @@ -237,10 +260,10 @@ fn test_write_characteristic_response() { // act: start write operation let data = build_view_or_crash(build_att_data(AttAttributeDataChild::RawData([1, 2].into()))); - let cloned_manager = callback_manager.clone(); + let datastore = callback_manager.get_datastore(SERVER_ID); let pending_write = spawn_local(async move { - cloned_manager - .write(CONN_ID, HANDLE_1, BACKING_TYPE, GattWriteRequestType::Request, data.view()) + datastore + .write(TCB_IDX, HANDLE_1, BACKING_TYPE, GattWriteRequestType::Request, data.view()) .await }); // provide a response with some error code @@ -262,9 +285,11 @@ fn test_response_timeout() { // act: start operation let time_sent = Instant::now(); - let pending_write = spawn_local(async move { - callback_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await - }); + let datastore = callback_manager.get_datastore(SERVER_ID); + let pending_write = + spawn_local( + async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }, + ); // assert: that we time-out after 15s assert_eq!(pending_write.await.unwrap(), Err(AttErrorCode::UNLIKELY_ERROR)); @@ -281,10 +306,11 @@ fn test_transaction_cleanup_after_timeout() { let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); // act: start an operation - let cloned_manager = callback_manager.clone(); - let pending = spawn_local(async move { - cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await - }); + let datastore = callback_manager.get_datastore(SERVER_ID); + let pending = + spawn_local( + async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }, + ); let trans_id = pull_trans_id(&mut callbacks_rx).await; // let it time out assert_eq!(pending.await.unwrap(), Err(AttErrorCode::UNLIKELY_ERROR)); @@ -304,10 +330,11 @@ fn test_listener_hang_up() { let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); // act: start an operation - let cloned_manager = callback_manager.clone(); - let pending = spawn_local(async move { - cloned_manager.read(CONN_ID, HANDLE_1, OFFSET, BACKING_TYPE).await - }); + let datastore = callback_manager.get_datastore(SERVER_ID); + let pending = + spawn_local( + async move { datastore.read(TCB_IDX, HANDLE_1, OFFSET, BACKING_TYPE).await }, + ); let trans_id = pull_trans_id(&mut callbacks_rx).await; // cancel the listener, wait for it to stop pending.abort(); @@ -330,7 +357,12 @@ fn test_write_no_response_callback() { // act: start write_no_response operation let data = build_view_or_crash(build_att_data(AttAttributeDataChild::RawData([1, 2].into()))); - callback_manager.write_no_response(CONN_ID, HANDLE_1, BACKING_TYPE, data.view()); + callback_manager.get_datastore(SERVER_ID).write_no_response( + TCB_IDX, + HANDLE_1, + BACKING_TYPE, + data.view(), + ); // assert: verify the write callback is received let MockCallbackEvents::OnServerWrite( @@ -352,9 +384,12 @@ fn test_execute_characteristic_callback() { let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); // act: start execute operation - spawn_local( - async move { callback_manager.execute(CONN_ID, TransactionDecision::Cancel).await }, - ); + spawn_local(async move { + callback_manager + .get_datastore(SERVER_ID) + .execute(TCB_IDX, TransactionDecision::Cancel) + .await + }); // assert: verify the execute callback is received let MockCallbackEvents::OnExecute( @@ -374,7 +409,10 @@ fn test_execute_characteristic_response() { // act: start execute operation let cloned_manager = callback_manager.clone(); let pending_execute = spawn_local(async move { - cloned_manager.execute(CONN_ID, TransactionDecision::Cancel).await + cloned_manager + .get_datastore(SERVER_ID) + .execute(TCB_IDX, TransactionDecision::Cancel) + .await }); // provide a response with some error code let trans_id = pull_trans_id(&mut callbacks_rx).await; diff --git a/system/rust/tests/gatt_server_test.rs b/system/rust/tests/gatt_server_test.rs index 5914ed8d19..8ec91f74e4 100644 --- a/system/rust/tests/gatt_server_test.rs +++ b/system/rust/tests/gatt_server_test.rs @@ -96,7 +96,7 @@ fn create_server_and_open_connection( }], }], }, - Rc::new(datastore), + datastore, ) .unwrap(); gatt.on_le_connect(CONN_ID).unwrap(); @@ -112,7 +112,7 @@ fn test_service_read() { create_server_and_open_connection(&mut gatt); // act - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttReadRequestBuilder { attribute_handle: SERVICE_HANDLE.into(), }) @@ -148,7 +148,7 @@ fn test_server_closed_while_connected() { gatt.close_gatt_server(SERVER_ID).unwrap(); // act: read from the closed server - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttReadRequestBuilder { attribute_handle: SERVICE_HANDLE.into(), }) @@ -181,14 +181,14 @@ fn test_characteristic_read() { let mut data_rx = create_server_and_open_connection(&mut gatt); // act - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttReadRequestBuilder { attribute_handle: CHARACTERISTIC_HANDLE.into(), }) .view(), ); let tx = if let MockDatastoreEvents::Read( - CONN_ID, + TCB_IDX, CHARACTERISTIC_HANDLE, AttributeBackingType::Characteristic, tx, @@ -224,7 +224,7 @@ fn test_characteristic_write() { let mut data_rx = create_server_and_open_connection(&mut gatt); // act - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttWriteRequestBuilder { handle: CHARACTERISTIC_HANDLE.into(), value: build_att_data(data.clone()), @@ -232,7 +232,7 @@ fn test_characteristic_write() { .view(), ); let (tx, written_data) = if let MockDatastoreEvents::Write( - CONN_ID, + TCB_IDX, CHARACTERISTIC_HANDLE, AttributeBackingType::Characteristic, written_data, @@ -274,12 +274,12 @@ fn test_send_indication() { // act let pending_indication = spawn_local( - gatt.get_bearer(CONN_ID).unwrap().send_indication(CHARACTERISTIC_HANDLE, data.clone()), + gatt.get_bearer(TCB_IDX).unwrap().send_indication(CHARACTERISTIC_HANDLE, data.clone()), ); let (tcb_idx, resp) = transport_rx.recv().await.unwrap(); - gatt.get_bearer(CONN_ID) + gatt.get_bearer(TCB_IDX) .unwrap() .handle_packet(build_att_view_or_crash(AttHandleValueConfirmationBuilder {}).view()); @@ -309,12 +309,12 @@ fn test_send_indication_and_disconnect() { create_server_and_open_connection(&mut gatt); // act: send an indication, then disconnect - let pending_indication = spawn_local(gatt.get_bearer(CONN_ID).unwrap().send_indication( + let pending_indication = spawn_local(gatt.get_bearer(TCB_IDX).unwrap().send_indication( CHARACTERISTIC_HANDLE, AttAttributeDataChild::RawData([1, 2, 3, 4].into()), )); transport_rx.recv().await.unwrap(); - gatt.on_le_disconnect(CONN_ID).unwrap(); + gatt.on_le_disconnect(TCB_IDX).unwrap(); // assert: the pending indication resolves appropriately assert!(matches!( @@ -335,7 +335,7 @@ fn test_write_to_descriptor() { let mut data_rx = create_server_and_open_connection(&mut gatt); // act - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttWriteRequestBuilder { handle: DESCRIPTOR_HANDLE.into(), value: build_att_data(data.clone()), @@ -343,7 +343,7 @@ fn test_write_to_descriptor() { .view(), ); let (tx, written_data) = if let MockDatastoreEvents::Write( - CONN_ID, + TCB_IDX, DESCRIPTOR_HANDLE, AttributeBackingType::Descriptor, written_data, @@ -397,19 +397,19 @@ fn test_multiple_servers() { descriptors: vec![], }], }, - Rc::new(datastore), + datastore, ) .unwrap(); gatt.on_le_connect(ANOTHER_CONN_ID).unwrap(); // act: read from both connections - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttReadRequestBuilder { attribute_handle: CHARACTERISTIC_HANDLE.into(), }) .view(), ); - gatt.get_bearer(ANOTHER_CONN_ID).unwrap().handle_packet( + gatt.get_bearer(ANOTHER_TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttReadRequestBuilder { attribute_handle: CHARACTERISTIC_HANDLE.into(), }) @@ -417,7 +417,7 @@ fn test_multiple_servers() { ); // service the first read with `data` let MockDatastoreEvents::Read( - CONN_ID, + TCB_IDX, _, _, tx, ) = data_rx_1.recv().await.unwrap() else { @@ -426,7 +426,7 @@ fn test_multiple_servers() { tx.send(Ok(data.clone())).unwrap(); // and then the second read with `another_data` let MockDatastoreEvents::Read( - ANOTHER_CONN_ID, + ANOTHER_TCB_IDX, _, _, tx, ) = data_rx_2.recv().await.unwrap() else { @@ -454,7 +454,7 @@ fn test_read_device_name() { create_server_and_open_connection(&mut gatt); // act: try to read the device name - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttReadByTypeRequestBuilder { starting_handle: AttHandle(1).into(), ending_handle: AttHandle(0xFFFF).into(), @@ -489,7 +489,7 @@ fn test_ignored_service_change_indication() { type_: SERVICE_TYPE, characteristics: vec![], }, - Rc::new(datastore), + datastore, ) .unwrap(); @@ -506,7 +506,7 @@ fn test_service_change_indication() { create_server_and_open_connection(&mut gatt); // act: discover the GATT server - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttFindByTypeValueRequestBuilder { starting_handle: AttHandle::MIN.into(), ending_handle: AttHandle::MAX.into(), @@ -525,7 +525,7 @@ fn test_service_change_indication() { resp.handles_info[0].clone().group_end_handle, ); // act: discover the service changed characteristic - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttReadByTypeRequestBuilder { starting_handle, ending_handle, @@ -547,7 +547,7 @@ fn test_service_change_indication() { } }).unwrap(); // act: find the CCC descriptor for the service changed characteristic - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttFindInformationRequestBuilder { starting_handle: service_change_char_handle.clone(), ending_handle: AttHandle::MAX.into(), @@ -573,7 +573,7 @@ fn test_service_change_indication() { }) .unwrap(); // act: register for indications on this handle - gatt.get_bearer(CONN_ID).unwrap().handle_packet( + gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttWriteRequestBuilder { handle: service_change_descriptor_handle, value: build_att_data(GattClientCharacteristicConfigurationBuilder { @@ -595,7 +595,7 @@ fn test_service_change_indication() { type_: SERVICE_TYPE, characteristics: vec![], }, - Rc::new(datastore), + datastore, ) .unwrap(); |