summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Rahul Arya <aryarahul@google.com> 2023-05-08 17:42:23 +0000
committer Rahul Arya <aryarahul@google.com> 2023-05-08 20:31:42 +0000
commitc0c40140e83d449f254e8a0a20e61b6dfb580293 (patch)
treebb7229405ba67b431b97c5a1ccfeb99e8e31b4d4
parent90fa684058835f926f8d755c4f311c131c7cfa43 (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.rs4
-rw-r--r--system/rust/src/gatt/arbiter.rs75
-rw-r--r--system/rust/src/gatt/callbacks.rs52
-rw-r--r--system/rust/src/gatt/callbacks/callback_transaction_manager.rs79
-rw-r--r--system/rust/src/gatt/ffi.rs4
-rw-r--r--system/rust/src/gatt/mocks/mock_database_callbacks.rs14
-rw-r--r--system/rust/src/gatt/mocks/mock_datastore.rs14
-rw-r--r--system/rust/src/gatt/mocks/mock_raw_datastore.rs26
-rw-r--r--system/rust/src/gatt/server.rs38
-rw-r--r--system/rust/src/gatt/server/att_server_bearer.rs8
-rw-r--r--system/rust/src/gatt/server/gatt_database.rs98
-rw-r--r--system/rust/src/gatt/server/services/gap.rs21
-rw-r--r--system/rust/src/gatt/server/services/gatt.rs55
-rw-r--r--system/rust/tests/gatt_callbacks_test.rs148
-rw-r--r--system/rust/tests/gatt_server_test.rs50
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();