diff options
author | 2024-06-10 19:26:38 -0700 | |
---|---|---|
committer | 2024-06-12 10:39:40 -0700 | |
commit | 6f91bd9dea04591976e4271fdb4401bfc1bc11bf (patch) | |
tree | 370510f7a807b91880b90e0841d8a67491893b99 | |
parent | 1077361f4ba2ddb4e715559ae0f4fed4f7d822b8 (diff) |
system/rust: Update GATT datastore interfaces to use raw values
The code almost never makes use of the structured type and mostly relies
on AttAttributeDataChild::RawData.
Removing this type will help convert the pdl rust backend later as the
generated type AttAttributeDataChild will no longer exist under this
form.
Bug: 331817295
Test: m com.android.btservices
Test: atest --host libbluetooth_core_rs_test
Flag: EXEMPT, mechanical refactor
Change-Id: I429341ed0ccc4a8cdaba7cc86d1249f16f11a28e
22 files changed, 268 insertions, 409 deletions
diff --git a/system/rust/src/gatt/callbacks.rs b/system/rust/src/gatt/callbacks.rs index a90e55c734..2d6a58cbdd 100644 --- a/system/rust/src/gatt/callbacks.rs +++ b/system/rust/src/gatt/callbacks.rs @@ -9,7 +9,7 @@ pub use callback_transaction_manager::{CallbackResponseError, CallbackTransactio use async_trait::async_trait; use log::warn; -use crate::packets::{AttAttributeDataChild, AttAttributeDataView, AttErrorCode}; +use crate::packets::AttErrorCode; use super::{ ffi::AttributeBackingType, @@ -41,7 +41,7 @@ pub trait GattCallbacks { handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteType, - value: AttAttributeDataView, + value: &[u8], ); /// Invoked when a handle value indication transaction completes @@ -102,7 +102,7 @@ pub trait RawGattDatastore { handle: AttHandle, offset: u32, attr_type: AttributeBackingType, - ) -> Result<AttAttributeDataChild, AttErrorCode>; + ) -> Result<Vec<u8>, AttErrorCode>; /// Write data to a given characteristic on the specified connection. async fn write( @@ -111,7 +111,7 @@ pub trait RawGattDatastore { handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, - data: AttAttributeDataView<'_>, + data: &[u8], ) -> Result<(), AttErrorCode>; /// Write data to a given characteristic on the specified connection, without waiting @@ -121,7 +121,7 @@ pub trait RawGattDatastore { tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, - data: AttAttributeDataView<'_>, + data: &[u8], ); /// Execute or cancel any prepared writes @@ -142,7 +142,7 @@ pub trait GattDatastore { tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, - ) -> Result<AttAttributeDataChild, AttErrorCode>; + ) -> Result<Vec<u8>, AttErrorCode>; /// Write data to a given characteristic on the specified connection. async fn write( @@ -150,7 +150,7 @@ pub trait GattDatastore { tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, - data: AttAttributeDataView<'_>, + data: &[u8], ) -> Result<(), AttErrorCode>; } @@ -163,7 +163,7 @@ impl<T: GattDatastore + ?Sized> RawGattDatastore for T { handle: AttHandle, offset: u32, attr_type: AttributeBackingType, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + ) -> Result<Vec<u8>, AttErrorCode> { if offset != 0 { warn!("got read blob request for non-long attribute {handle:?}"); return Err(AttErrorCode::ATTRIBUTE_NOT_LONG); @@ -178,7 +178,7 @@ impl<T: GattDatastore + ?Sized> RawGattDatastore for T { handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, - data: AttAttributeDataView<'_>, + data: &[u8], ) -> Result<(), AttErrorCode> { match write_type { GattWriteRequestType::Prepare { .. } => { @@ -194,7 +194,7 @@ impl<T: GattDatastore + ?Sized> RawGattDatastore for T { tcb_idx: TransportIndex, handle: AttHandle, _: AttributeBackingType, - _: AttAttributeDataView<'_>, + _: &[u8], ) { // silently drop, since there's no way to return an error warn!("got write command on {tcb_idx:?} to characteristic {handle:?} not supporting write_without_response"); @@ -213,11 +213,7 @@ mod test { use crate::{ gatt::mocks::mock_datastore::{MockDatastore, MockDatastoreEvents}, - packets::OwnedAttAttributeDataView, - utils::{ - packet::{build_att_data, build_view_or_crash}, - task::block_on_locally, - }, + utils::task::block_on_locally, }; use super::*; @@ -301,10 +297,6 @@ mod test { assert_eq!(rx.try_recv().unwrap_err(), TryRecvError::Empty); } - fn make_data() -> OwnedAttAttributeDataView { - build_view_or_crash(build_att_data(AttAttributeDataChild::RawData(DATA.into()))) - } - #[test] fn test_write_request_invoke() { block_on_locally(async { @@ -319,7 +311,7 @@ mod test { HANDLE, AttributeBackingType::Characteristic, GattWriteRequestType::Request, - make_data().view(), + &DATA, ) .await }); @@ -353,7 +345,7 @@ mod test { HANDLE, AttributeBackingType::Characteristic, GattWriteRequestType::Request, - make_data().view(), + &DATA, ) .await }); @@ -380,7 +372,7 @@ mod test { HANDLE, AttributeBackingType::Characteristic, GattWriteRequestType::Prepare { offset: 1 }, - make_data().view(), + &DATA, )); // assert: got the correct error code @@ -400,7 +392,7 @@ mod test { TCB_IDX, HANDLE, AttributeBackingType::Characteristic, - make_data().view(), + &DATA, ); // assert: no event sent up diff --git a/system/rust/src/gatt/callbacks/callback_transaction_manager.rs b/system/rust/src/gatt/callbacks/callback_transaction_manager.rs index c9c9862c81..4210d64535 100644 --- a/system/rust/src/gatt/callbacks/callback_transaction_manager.rs +++ b/system/rust/src/gatt/callbacks/callback_transaction_manager.rs @@ -9,7 +9,7 @@ use crate::{ ids::{AttHandle, ConnectionId, ServerId, TransactionId, TransportIndex}, GattCallbacks, }, - packets::{AttAttributeDataChild, AttAttributeDataView, AttErrorCode}, + packets::AttErrorCode, }; use super::{ @@ -18,14 +18,14 @@ use super::{ }; struct PendingTransaction { - response: oneshot::Sender<Result<AttAttributeDataChild, AttErrorCode>>, + response: oneshot::Sender<Result<Vec<u8>, AttErrorCode>>, } #[derive(Debug)] struct PendingTransactionWatcher { conn_id: ConnectionId, trans_id: TransactionId, - rx: oneshot::Receiver<Result<AttAttributeDataChild, AttErrorCode>>, + rx: oneshot::Receiver<Result<Vec<u8>, AttErrorCode>>, } /// This struct converts the asynchronus read/write operations of GattDatastore @@ -72,7 +72,7 @@ impl CallbackTransactionManager { &self, conn_id: ConnectionId, trans_id: TransactionId, - value: Result<AttAttributeDataChild, AttErrorCode>, + value: Result<Vec<u8>, AttErrorCode>, ) -> Result<(), CallbackResponseError> { let mut pending = self.pending_transactions.borrow_mut(); if let Some(transaction) = pending.pending_transactions.remove(&(conn_id, trans_id)) { @@ -111,10 +111,7 @@ impl PendingTransactionsState { impl PendingTransactionWatcher { /// Wait for the transaction to resolve, or to hit the timeout. If the /// timeout is reached, clean up state related to transaction watching. - async fn wait( - self, - manager: &CallbackTransactionManager, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + async fn wait(self, manager: &CallbackTransactionManager) -> Result<Vec<u8>, AttErrorCode> { if let Ok(Ok(result)) = timeout(TIMEOUT, self.rx).await { result } else { @@ -142,7 +139,7 @@ impl RawGattDatastore for GattDatastoreImpl { handle: AttHandle, offset: u32, attr_type: AttributeBackingType, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + ) -> Result<Vec<u8>, AttErrorCode> { let conn_id = ConnectionId::new(tcb_idx, self.server_id); let pending_transaction = self @@ -169,7 +166,7 @@ impl RawGattDatastore for GattDatastoreImpl { handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, - data: AttAttributeDataView<'_>, + data: &[u8], ) -> Result<(), AttErrorCode> { let conn_id = ConnectionId::new(tcb_idx, self.server_id); @@ -198,7 +195,7 @@ impl RawGattDatastore for GattDatastoreImpl { tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, - data: AttAttributeDataView<'_>, + data: &[u8], ) { let conn_id = ConnectionId::new(tcb_idx, self.server_id); diff --git a/system/rust/src/gatt/ffi.rs b/system/rust/src/gatt/ffi.rs index d21c23dd1c..d5a9ec7a2d 100644 --- a/system/rust/src/gatt/ffi.rs +++ b/system/rust/src/gatt/ffi.rs @@ -12,10 +12,7 @@ use tokio::task::spawn_local; use crate::{ do_in_rust_thread, - packets::{ - AttAttributeDataChild, AttAttributeDataView, AttBuilder, AttErrorCode, Serializable, - SerializeError, - }, + packets::{AttAttributeDataChild, AttBuilder, AttErrorCode, Serializable, SerializeError}, }; use super::{ @@ -213,7 +210,7 @@ impl GattCallbacks for GattCallbacksImpl { handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteType, - value: AttAttributeDataView, + value: &[u8], ) { trace!( "on_server_write ({conn_id:?}, {trans_id:?}, {handle:?}, {attr_type:?}, {write_type:?}" @@ -229,7 +226,7 @@ impl GattCallbacks for GattCallbacksImpl { }, matches!(write_type, GattWriteType::Request { .. }), matches!(write_type, GattWriteType::Request(GattWriteRequestType::Prepare { .. })), - &value.get_raw_payload().collect::<Vec<_>>(), + value, ); } @@ -419,7 +416,7 @@ fn send_response(_server_id: u8, conn_id: u16, trans_id: u32, status: u8, value: // TODO(aryarahul): fixup error codes to allow app-specific values (i.e. don't // make it an enum in PDL) let value = if status == 0 { - Ok(AttAttributeDataChild::RawData(value.to_vec().into_boxed_slice())) + Ok(value.to_vec()) } else { Err(AttErrorCode::try_from(status).unwrap_or(AttErrorCode::UNLIKELY_ERROR)) }; diff --git a/system/rust/src/gatt/mocks/mock_callbacks.rs b/system/rust/src/gatt/mocks/mock_callbacks.rs index a5dbee253f..14a8da7a6b 100644 --- a/system/rust/src/gatt/mocks/mock_callbacks.rs +++ b/system/rust/src/gatt/mocks/mock_callbacks.rs @@ -1,14 +1,11 @@ //! Mocked implementation of GattCallbacks for use in test -use crate::{ - gatt::{ - callbacks::{GattWriteType, TransactionDecision}, - ffi::AttributeBackingType, - ids::{AttHandle, ConnectionId, TransactionId}, - server::IndicationError, - GattCallbacks, - }, - packets::{AttAttributeDataView, OwnedAttAttributeDataView, Packet}, +use crate::gatt::{ + callbacks::{GattWriteType, TransactionDecision}, + ffi::AttributeBackingType, + ids::{AttHandle, ConnectionId, TransactionId}, + server::IndicationError, + GattCallbacks, }; use tokio::sync::mpsc::{self, unbounded_channel, UnboundedReceiver}; @@ -35,7 +32,7 @@ pub enum MockCallbackEvents { AttHandle, AttributeBackingType, GattWriteType, - OwnedAttAttributeDataView, + Vec<u8>, ), /// GattCallbacks#on_indication_sent_confirmation invoked OnIndicationSentConfirmation(ConnectionId, Result<(), IndicationError>), @@ -64,7 +61,7 @@ impl GattCallbacks for MockCallbacks { handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteType, - value: AttAttributeDataView, + value: &[u8], ) { self.0 .send(MockCallbackEvents::OnServerWrite( @@ -73,7 +70,7 @@ impl GattCallbacks for MockCallbacks { handle, attr_type, write_type, - value.to_owned_packet(), + value.to_vec(), )) .unwrap(); } diff --git a/system/rust/src/gatt/mocks/mock_datastore.rs b/system/rust/src/gatt/mocks/mock_datastore.rs index e21889421f..901fe75565 100644 --- a/system/rust/src/gatt/mocks/mock_datastore.rs +++ b/system/rust/src/gatt/mocks/mock_datastore.rs @@ -6,10 +6,7 @@ use crate::{ ffi::AttributeBackingType, ids::{AttHandle, TransportIndex}, }, - packets::{ - AttAttributeDataChild, AttAttributeDataView, AttErrorCode, OwnedAttAttributeDataView, - Packet, - }, + packets::AttErrorCode, }; use async_trait::async_trait; use log::info; @@ -38,7 +35,7 @@ pub enum MockDatastoreEvents { TransportIndex, AttHandle, AttributeBackingType, - oneshot::Sender<Result<AttAttributeDataChild, AttErrorCode>>, + oneshot::Sender<Result<Vec<u8>, AttErrorCode>>, ), /// A characteristic was written to on a given handle. The oneshot is used /// to return whether the write succeeded. @@ -46,7 +43,7 @@ pub enum MockDatastoreEvents { TransportIndex, AttHandle, AttributeBackingType, - OwnedAttAttributeDataView, + Vec<u8>, oneshot::Sender<Result<(), AttErrorCode>>, ), } @@ -58,7 +55,7 @@ impl GattDatastore for MockDatastore { tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + ) -> Result<Vec<u8>, AttErrorCode> { let (tx, rx) = oneshot::channel(); self.0.send(MockDatastoreEvents::Read(tcb_idx, handle, attr_type, tx)).unwrap(); let resp = rx.await.unwrap(); @@ -71,17 +68,11 @@ impl GattDatastore for MockDatastore { tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, - data: AttAttributeDataView<'_>, + data: &[u8], ) -> Result<(), AttErrorCode> { let (tx, rx) = oneshot::channel(); self.0 - .send(MockDatastoreEvents::Write( - tcb_idx, - handle, - attr_type, - data.to_owned_packet(), - tx, - )) + .send(MockDatastoreEvents::Write(tcb_idx, handle, attr_type, data.to_vec(), tx)) .unwrap(); rx.await.unwrap() } diff --git a/system/rust/src/gatt/mocks/mock_raw_datastore.rs b/system/rust/src/gatt/mocks/mock_raw_datastore.rs index 7d4055ca2e..0deb220d28 100644 --- a/system/rust/src/gatt/mocks/mock_raw_datastore.rs +++ b/system/rust/src/gatt/mocks/mock_raw_datastore.rs @@ -6,10 +6,7 @@ use crate::{ ffi::AttributeBackingType, ids::{AttHandle, TransportIndex}, }, - packets::{ - AttAttributeDataChild, AttAttributeDataView, AttErrorCode, OwnedAttAttributeDataView, - Packet, - }, + packets::AttErrorCode, }; use async_trait::async_trait; use log::info; @@ -39,7 +36,7 @@ pub enum MockRawDatastoreEvents { AttHandle, AttributeBackingType, u32, - oneshot::Sender<Result<AttAttributeDataChild, AttErrorCode>>, + oneshot::Sender<Result<Vec<u8>, AttErrorCode>>, ), /// A characteristic was written to on a given handle. The oneshot is used /// to return whether the write succeeded. @@ -48,11 +45,11 @@ pub enum MockRawDatastoreEvents { AttHandle, AttributeBackingType, GattWriteRequestType, - OwnedAttAttributeDataView, + Vec<u8>, oneshot::Sender<Result<(), AttErrorCode>>, ), /// A characteristic was written to on a given handle, where the response was disregarded. - WriteNoResponse(TransportIndex, AttHandle, AttributeBackingType, OwnedAttAttributeDataView), + WriteNoResponse(TransportIndex, AttHandle, AttributeBackingType, Vec<u8>), /// The prepared writes have been committed / aborted. The oneshot is used /// to return whether this operation succeeded. Execute(TransportIndex, TransactionDecision, oneshot::Sender<Result<(), AttErrorCode>>), @@ -66,7 +63,7 @@ impl RawGattDatastore for MockRawDatastore { handle: AttHandle, offset: u32, attr_type: AttributeBackingType, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + ) -> Result<Vec<u8>, AttErrorCode> { let (tx, rx) = oneshot::channel(); self.0.send(MockRawDatastoreEvents::Read(tcb_idx, handle, attr_type, offset, tx)).unwrap(); let resp = rx.await.unwrap(); @@ -80,7 +77,7 @@ impl RawGattDatastore for MockRawDatastore { handle: AttHandle, attr_type: AttributeBackingType, write_type: GattWriteRequestType, - data: AttAttributeDataView<'_>, + data: &[u8], ) -> Result<(), AttErrorCode> { let (tx, rx) = oneshot::channel(); self.0 @@ -89,7 +86,7 @@ impl RawGattDatastore for MockRawDatastore { handle, attr_type, write_type, - data.to_owned_packet(), + data.to_vec(), tx, )) .unwrap(); @@ -101,14 +98,14 @@ impl RawGattDatastore for MockRawDatastore { tcb_idx: TransportIndex, handle: AttHandle, attr_type: AttributeBackingType, - data: AttAttributeDataView<'_>, + data: &[u8], ) { self.0 .send(MockRawDatastoreEvents::WriteNoResponse( tcb_idx, handle, attr_type, - data.to_owned_packet(), + data.to_vec(), )) .unwrap(); } diff --git a/system/rust/src/gatt/server/att_database.rs b/system/rust/src/gatt/server/att_database.rs index 2235fd81f5..47e67270a2 100644 --- a/system/rust/src/gatt/server/att_database.rs +++ b/system/rust/src/gatt/server/att_database.rs @@ -4,9 +4,7 @@ use bitflags::bitflags; use crate::{ core::uuid::Uuid, gatt::ids::AttHandle, - packets::{ - AttAttributeDataChild, AttAttributeDataView, AttErrorCode, AttHandleBuilder, AttHandleView, - }, + packets::{AttErrorCode, AttHandleBuilder, AttHandleView}, }; impl From<AttHandleView<'_>> for AttHandle { @@ -69,20 +67,13 @@ impl AttPermissions { #[async_trait(?Send)] pub trait AttDatabase { /// Read an attribute by handle - async fn read_attribute( - &self, - handle: AttHandle, - ) -> Result<AttAttributeDataChild, AttErrorCode>; + async fn read_attribute(&self, handle: AttHandle) -> Result<Vec<u8>, AttErrorCode>; /// Write to an attribute by handle - async fn write_attribute( - &self, - handle: AttHandle, - data: AttAttributeDataView<'_>, - ) -> Result<(), AttErrorCode>; + async fn write_attribute(&self, handle: AttHandle, data: &[u8]) -> Result<(), AttErrorCode>; /// Write to an attribute by handle - fn write_no_response_attribute(&self, handle: AttHandle, data: AttAttributeDataView<'_>); + fn write_no_response_attribute(&self, handle: AttHandle, data: &[u8]); /// List all the attributes in this database. /// @@ -117,22 +108,15 @@ pub struct SnapshottedAttDatabase<'a> { #[async_trait(?Send)] impl AttDatabase for SnapshottedAttDatabase<'_> { - async fn read_attribute( - &self, - handle: AttHandle, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + async fn read_attribute(&self, handle: AttHandle) -> Result<Vec<u8>, AttErrorCode> { self.backing.read_attribute(handle).await } - async fn write_attribute( - &self, - handle: AttHandle, - data: AttAttributeDataView<'_>, - ) -> Result<(), AttErrorCode> { + async fn write_attribute(&self, handle: AttHandle, data: &[u8]) -> Result<(), AttErrorCode> { self.backing.write_attribute(handle, data).await } - fn write_no_response_attribute(&self, handle: AttHandle, data: AttAttributeDataView<'_>) { + fn write_no_response_attribute(&self, handle: AttHandle, data: &[u8]) { self.backing.write_no_response_attribute(handle, data); } diff --git a/system/rust/src/gatt/server/att_server_bearer.rs b/system/rust/src/gatt/server/att_server_bearer.rs index c8b7a38241..d2d732fc7a 100644 --- a/system/rust/src/gatt/server/att_server_bearer.rs +++ b/system/rust/src/gatt/server/att_server_bearer.rs @@ -238,11 +238,11 @@ mod test { }, }, packets::{ - AttAttributeDataChild, AttHandleValueConfirmationBuilder, AttOpcode, - AttReadRequestBuilder, AttReadResponseBuilder, + AttAttributeDataBuilder, AttAttributeDataChild, AttHandleValueConfirmationBuilder, + AttOpcode, AttReadRequestBuilder, AttReadResponseBuilder, }, utils::{ - packet::{build_att_data, build_att_view_or_crash}, + packet::build_att_view_or_crash, task::{block_on_locally, try_await}, }, }; @@ -356,7 +356,7 @@ mod test { Ok(()) }; let conn = SharedBox::new(AttServerBearer::new(db.get_att_database(TCB_IDX), send_packet)); - let data = AttAttributeDataChild::RawData([1, 2].into()); + let data = [1, 2]; // act: send two read requests before replying to either read // first request @@ -380,7 +380,7 @@ mod test { else { unreachable!(); }; - data_resp.send(Ok(data.clone())).unwrap(); + data_resp.send(Ok(data.to_vec())).unwrap(); trace!("reply sent from upper tester"); // assert: that the first reply was made @@ -389,7 +389,14 @@ mod test { resp, AttBuilder { opcode: AttOpcode::READ_RESPONSE, - _child_: AttReadResponseBuilder { value: build_att_data(data) }.into(), + _child_: AttReadResponseBuilder { + value: AttAttributeDataBuilder { + _child_: AttAttributeDataChild::RawData( + data.to_vec().into_boxed_slice() + ) + }, + } + .into() } ); // assert no other replies were made diff --git a/system/rust/src/gatt/server/command_handler.rs b/system/rust/src/gatt/server/command_handler.rs index 365ed3bc1e..a147584da9 100644 --- a/system/rust/src/gatt/server/command_handler.rs +++ b/system/rust/src/gatt/server/command_handler.rs @@ -22,8 +22,10 @@ impl<Db: AttDatabase> AttCommandHandler<Db> { warn!("failed to parse WRITE_COMMAND packet"); return; }; - snapshotted_db - .write_no_response_attribute(packet.get_handle().into(), packet.get_value()); + snapshotted_db.write_no_response_attribute( + packet.get_handle().into(), + &packet.get_value().get_raw_payload().collect::<Vec<_>>(), + ); } _ => { warn!("Dropping unsupported opcode {:?}", packet.get_opcode()); @@ -46,13 +48,10 @@ mod test { }, }, packets::{ - AttAttributeDataChild, AttErrorCode, AttErrorResponseBuilder, AttOpcode, - AttWriteCommandBuilder, - }, - utils::{ - packet::{build_att_data, build_att_view_or_crash}, - task::block_on_locally, + AttAttributeDataBuilder, AttAttributeDataChild, AttErrorCode, AttErrorResponseBuilder, + AttOpcode, AttWriteCommandBuilder, }, + utils::{packet::build_att_view_or_crash, task::block_on_locally}, }; #[test] @@ -67,12 +66,14 @@ mod test { vec![1, 2, 3], )]); let handler = AttCommandHandler { db: db.clone() }; - let data = AttAttributeDataChild::RawData([1, 2].into()); + let data = [1, 2]; // act: send write command let att_view = build_att_view_or_crash(AttWriteCommandBuilder { handle: AttHandle(3).into(), - value: build_att_data(data.clone()), + value: AttAttributeDataBuilder { + _child_: AttAttributeDataChild::RawData(data.to_vec().into_boxed_slice()), + }, }); handler.process_packet(att_view.view()); diff --git a/system/rust/src/gatt/server/gatt_database.rs b/system/rust/src/gatt/server/gatt_database.rs index 806ab4e7c2..baffd17773 100644 --- a/system/rust/src/gatt/server/gatt_database.rs +++ b/system/rust/src/gatt/server/gatt_database.rs @@ -19,9 +19,9 @@ use crate::{ ids::{AttHandle, TransportIndex}, }, packets::{ - AttAttributeDataChild, AttAttributeDataView, AttErrorCode, - GattCharacteristicDeclarationValueBuilder, GattCharacteristicPropertiesBuilder, - GattServiceDeclarationValueBuilder, UuidBuilder, + AttErrorCode, GattCharacteristicDeclarationValueBuilder, + GattCharacteristicPropertiesBuilder, GattServiceDeclarationValueBuilder, Serializable, + UuidBuilder, }, }; @@ -98,7 +98,7 @@ struct GattDatabaseSchema { #[derive(Clone)] enum AttAttributeBackingValue { - Static(AttAttributeDataChild), + Static(Vec<u8>), DynamicCharacteristic(Rc<dyn RawGattDatastore>), DynamicDescriptor(Rc<dyn RawGattDatastore>), } @@ -187,7 +187,10 @@ impl GattDatabase { }, AttAttributeBackingValue::Static( GattServiceDeclarationValueBuilder { uuid: UuidBuilder::from(service.type_) } - .into(), + .to_vec() + .map_err(|e| { + anyhow::anyhow!("failed to encode primary service declaration: {e:?}") + })?, ), ); @@ -224,7 +227,10 @@ impl GattDatabase { handle: characteristic.handle.into(), uuid: characteristic.type_.into(), } - .into(), + .to_vec() + .map_err(|e| { + anyhow::anyhow!("failed to encode characteristic declaration: {e:?}") + })?, ), ); @@ -341,10 +347,7 @@ pub struct AttDatabaseImpl { #[async_trait(?Send)] impl AttDatabase for AttDatabaseImpl { - async fn read_attribute( - &self, - handle: AttHandle, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + async fn read_attribute(&self, handle: AttHandle) -> Result<Vec<u8>, AttErrorCode> { let value = self.gatt_db.with(|gatt_db| { let Some(gatt_db) = gatt_db else { // db must have been closed @@ -385,11 +388,7 @@ impl AttDatabase for AttDatabaseImpl { } } - async fn write_attribute( - &self, - handle: AttHandle, - data: AttAttributeDataView<'_>, - ) -> Result<(), AttErrorCode> { + async fn write_attribute(&self, handle: AttHandle, data: &[u8]) -> Result<(), AttErrorCode> { let value = self.gatt_db.with(|gatt_db| { let Some(gatt_db) = gatt_db else { // db must have been closed @@ -435,7 +434,7 @@ impl AttDatabase for AttDatabaseImpl { } } - fn write_no_response_attribute(&self, handle: AttHandle, data: AttAttributeDataView<'_>) { + fn write_no_response_attribute(&self, handle: AttHandle, data: &[u8]) { let value = self.gatt_db.with(|gatt_db| { let Some(gatt_db) = gatt_db else { // db must have been closed @@ -522,11 +521,8 @@ mod test { mock_datastore::{MockDatastore, MockDatastoreEvents}, mock_raw_datastore::{MockRawDatastore, MockRawDatastoreEvents}, }, - packets::Packet, - utils::{ - packet::{build_att_data, build_view_or_crash}, - task::block_on_locally, - }, + packets::AttAttributeDataChild, + utils::task::block_on_locally, }; use super::*; @@ -582,9 +578,11 @@ mod test { ); assert_eq!( service_value, - Ok(AttAttributeDataChild::GattServiceDeclarationValue( + AttAttributeDataChild::GattServiceDeclarationValue( GattServiceDeclarationValueBuilder { uuid: SERVICE_TYPE.into() } - )) + ) + .to_vec() + .map_err(|_| AttErrorCode::UNLIKELY_ERROR) ); } @@ -719,7 +717,7 @@ mod test { assert_eq!( characteristic_decl, - Ok(AttAttributeDataChild::GattCharacteristicDeclarationValue( + AttAttributeDataChild::GattCharacteristicDeclarationValue( GattCharacteristicDeclarationValueBuilder { properties: GattCharacteristicPropertiesBuilder { read: 1, @@ -734,7 +732,9 @@ mod test { handle: CHARACTERISTIC_VALUE_HANDLE.into(), uuid: CHARACTERISTIC_TYPE.into() } - )) + ) + .to_vec() + .map_err(|_| AttErrorCode::UNLIKELY_ERROR) ); } @@ -767,7 +767,7 @@ mod test { tokio_test::block_on(att_db.read_attribute(CHARACTERISTIC_DECLARATION_HANDLE)); assert_eq!( characteristic_decl, - Ok(AttAttributeDataChild::GattCharacteristicDeclarationValue( + AttAttributeDataChild::GattCharacteristicDeclarationValue( GattCharacteristicDeclarationValueBuilder { properties: GattCharacteristicPropertiesBuilder { read: 1, @@ -782,7 +782,9 @@ mod test { handle: CHARACTERISTIC_VALUE_HANDLE.into(), uuid: CHARACTERISTIC_TYPE.into() } - )) + ) + .to_vec() + .map_err(|_| AttErrorCode::UNLIKELY_ERROR) ); } @@ -807,7 +809,7 @@ mod test { ) .unwrap(); let att_db = gatt_db.get_att_database(TCB_IDX); - let data = AttAttributeDataChild::RawData(Box::new([1, 2])); + let data = [1, 2]; // act: read from the database, and supply a value from the backing datastore let characteristic_value = tokio_test::block_on(async { @@ -822,7 +824,7 @@ mod test { else { unreachable!() }; - reply.send(Ok(data.clone())).unwrap(); + reply.send(Ok(data.to_vec())).unwrap(); }, att_db.read_attribute(CHARACTERISTIC_VALUE_HANDLE) ) @@ -830,7 +832,7 @@ mod test { }); // assert: the supplied value matches what the att datastore returned - assert_eq!(characteristic_value, Ok(data)); + assert_eq!(characteristic_value, Ok(data.to_vec())); } #[test] @@ -932,18 +934,13 @@ mod test { ) .unwrap(); 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])))); + let data = [1, 2]; // act: write to the database let recv_data = block_on_locally(async { // start write task - let cloned_data = data.view().to_owned_packet(); spawn_local(async move { - att_db - .write_attribute(CHARACTERISTIC_VALUE_HANDLE, cloned_data.view()) - .await - .unwrap(); + att_db.write_attribute(CHARACTERISTIC_VALUE_HANDLE, &data).await.unwrap(); }); let MockDatastoreEvents::Write( @@ -960,10 +957,7 @@ mod test { }); // assert: the received value matches what we supplied - assert_eq!( - recv_data.view().get_raw_payload().collect::<Vec<_>>(), - data.view().get_raw_payload().collect::<Vec<_>>() - ); + assert_eq!(recv_data, data); } #[test] @@ -987,8 +981,7 @@ mod test { ) .unwrap(); 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])))); + let data = [1, 2]; // act: write to the database let res = tokio_test::block_on(async { @@ -1001,7 +994,7 @@ mod test { }; reply.send(Err(AttErrorCode::UNLIKELY_ERROR)).unwrap(); }, - att_db.write_attribute(CHARACTERISTIC_VALUE_HANDLE, data.view()) + att_db.write_attribute(CHARACTERISTIC_VALUE_HANDLE, &data) ) .1 }); @@ -1029,13 +1022,10 @@ mod test { Rc::new(gatt_datastore), ) .unwrap(); - let data = - build_view_or_crash(build_att_data(AttAttributeDataChild::RawData(Box::new([1, 2])))); + let data = [1, 2]; let characteristic_value = tokio_test::block_on( - gatt_db - .get_att_database(TCB_IDX) - .write_attribute(CHARACTERISTIC_VALUE_HANDLE, data.view()), + gatt_db.get_att_database(TCB_IDX).write_attribute(CHARACTERISTIC_VALUE_HANDLE, &data), ); assert_eq!(characteristic_value, Err(AttErrorCode::WRITE_NOT_PERMITTED)); @@ -1065,7 +1055,7 @@ mod test { ) .unwrap(); let att_db = gatt_db.get_att_database(TCB_IDX); - let data = AttAttributeDataChild::RawData(Box::new([1, 2])); + let data = [1, 2]; let descriptor_value = block_on_locally(async { // start write task @@ -1082,7 +1072,7 @@ mod test { unreachable!(); }; - reply.send(Ok(data.clone())).unwrap(); + reply.send(Ok(data.to_vec())).unwrap(); pending_read.await.unwrap() }); @@ -1115,15 +1105,14 @@ mod test { ) .unwrap(); 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])))); + let data = [1, 2]; // act: write, and wait for the callback to be invoked block_on_locally(async { // start write task - spawn_local(async move { - att_db.write_attribute(DESCRIPTOR_HANDLE, data.view()).await.unwrap() - }); + spawn_local( + async move { att_db.write_attribute(DESCRIPTOR_HANDLE, &data).await.unwrap() }, + ); let MockDatastoreEvents::Write( TCB_IDX, @@ -1251,7 +1240,7 @@ mod test { .unwrap(); let att_db = gatt_db.get_att_database(TCB_IDX); - let data = AttAttributeDataChild::RawData(Box::new([1, 2])); + let data = [1, 2]; // act: read from the second characteristic and supply a response from the second datastore let characteristic_value = tokio_test::block_on(async { @@ -1266,7 +1255,7 @@ mod test { else { unreachable!() }; - reply.send(Ok(data.clone())).unwrap(); + reply.send(Ok(data.to_vec())).unwrap(); }, att_db.read_attribute(AttHandle(6)) ) @@ -1274,7 +1263,7 @@ mod test { }); // assert: the supplied value matches what the att datastore returned - assert_eq!(characteristic_value, Ok(data)); + assert_eq!(characteristic_value, Ok(data.to_vec())); // the first datastore received no events assert_eq!(data_evts_1.try_recv().unwrap_err(), TryRecvError::Empty); // the second datastore has no remaining events @@ -1510,11 +1499,10 @@ mod test { ) .unwrap(); 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])))); + let data = [1, 2]; // act: write without response to the database - att_db.write_no_response_attribute(CHARACTERISTIC_VALUE_HANDLE, data.view()); + att_db.write_no_response_attribute(CHARACTERISTIC_VALUE_HANDLE, &data); // assert: we got a callback let event = data_evts.blocking_recv().unwrap(); @@ -1527,10 +1515,7 @@ mod test { else { unreachable!("{event:?}"); }; - assert_eq!( - recv_data.view().get_raw_payload().collect::<Vec<_>>(), - data.view().get_raw_payload().collect::<Vec<_>>() - ); + assert_eq!(recv_data, data); } #[test] @@ -1555,11 +1540,10 @@ mod test { ) .unwrap(); 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])))); + let data = [1, 2]; // act: try writing without response to this characteristic - att_db.write_no_response_attribute(CHARACTERISTIC_VALUE_HANDLE, data.view()); + att_db.write_no_response_attribute(CHARACTERISTIC_VALUE_HANDLE, &data); // assert: no callback was sent assert_eq!(data_events.try_recv().unwrap_err(), TryRecvError::Empty); diff --git a/system/rust/src/gatt/server/services/gap.rs b/system/rust/src/gatt/server/services/gap.rs index c601587a18..f5476301ff 100644 --- a/system/rust/src/gatt/server/services/gap.rs +++ b/system/rust/src/gatt/server/services/gap.rs @@ -15,7 +15,7 @@ use crate::{ AttPermissions, GattCharacteristicWithHandle, GattDatabase, GattServiceWithHandle, }, }, - packets::{AttAttributeDataChild, AttAttributeDataView, AttErrorCode}, + packets::AttErrorCode, }; struct GapService; @@ -39,7 +39,7 @@ impl GattDatastore for GapService { _: TransportIndex, handle: AttHandle, _: AttributeBackingType, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + ) -> Result<Vec<u8>, AttErrorCode> { match handle { DEVICE_NAME_HANDLE => { // for non-bonded peers, don't let them read the device name @@ -47,7 +47,7 @@ impl GattDatastore for GapService { Err(AttErrorCode::INSUFFICIENT_AUTHENTICATION) } // 0x0000 from AssignedNumbers => "Unknown" - DEVICE_APPEARANCE_HANDLE => Ok(AttAttributeDataChild::RawData([0x00, 0x00].into())), + DEVICE_APPEARANCE_HANDLE => Ok(vec![0x00, 0x00]), _ => unreachable!("unexpected handle read"), } } @@ -57,7 +57,7 @@ impl GattDatastore for GapService { _: TransportIndex, _: AttHandle, _: AttributeBackingType, - _: AttAttributeDataView<'_>, + _: &[u8], ) -> Result<(), AttErrorCode> { unreachable!("no GAP data should be writable") } @@ -160,6 +160,6 @@ mod test { let name = block_on_locally(att_db.read_attribute(DEVICE_APPEARANCE_HANDLE)); // assert: the name is not readable - assert_eq!(name, Ok(AttAttributeDataChild::RawData([0x00, 0x00].into()))); + assert_eq!(name, Ok(vec![0x00, 0x00])); } } diff --git a/system/rust/src/gatt/server/services/gatt.rs b/system/rust/src/gatt/server/services/gatt.rs index ba42a0ca6d..5bb6ce5f89 100644 --- a/system/rust/src/gatt/server/services/gatt.rs +++ b/system/rust/src/gatt/server/services/gatt.rs @@ -25,9 +25,8 @@ use crate::{ }, }, packets::{ - AttAttributeDataChild, AttAttributeDataView, AttErrorCode, - GattClientCharacteristicConfigurationBuilder, GattClientCharacteristicConfigurationView, - GattServiceChangedBuilder, Packet, + AttErrorCode, GattClientCharacteristicConfigurationBuilder, + GattClientCharacteristicConfigurationView, GattServiceChangedBuilder, Packet, Serializable, }, }; @@ -61,9 +60,9 @@ impl GattDatastore for GattService { tcb_idx: TransportIndex, handle: AttHandle, _: AttributeBackingType, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + ) -> Result<Vec<u8>, AttErrorCode> { if handle == SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE { - Ok(GattClientCharacteristicConfigurationBuilder { + GattClientCharacteristicConfigurationBuilder { notification: 0, indication: self .clients @@ -73,7 +72,8 @@ impl GattDatastore for GattService { .unwrap_or(false) .into(), } - .into()) + .to_vec() + .map_err(|_| AttErrorCode::UNLIKELY_ERROR) } else { unreachable!() } @@ -84,11 +84,11 @@ impl GattDatastore for GattService { tcb_idx: TransportIndex, handle: AttHandle, _: AttributeBackingType, - data: AttAttributeDataView<'_>, + data: &[u8], ) -> Result<(), AttErrorCode> { if handle == SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE { - let ccc = - GattClientCharacteristicConfigurationView::try_parse(data).map_err(|err| { + let ccc = GattClientCharacteristicConfigurationView::try_parse_from_buffer(data) + .map_err(|err| { warn!("failed to parse CCC descriptor, got: {err:?}"); AttErrorCode::APPLICATION_ERROR })?; @@ -190,11 +190,8 @@ mod test { }, }, }, - packets::{AttBuilder, AttChild}, - utils::{ - packet::{build_att_data, build_view_or_crash}, - task::{block_on_locally, try_await}, - }, + packets::{AttAttributeDataChild, AttBuilder, AttChild}, + utils::task::{block_on_locally, try_await}, }; const TCB_IDX: TransportIndex = TransportIndex(1); @@ -260,14 +257,10 @@ mod test { let resp = block_on_locally(att_db.read_attribute(SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE)).unwrap(); - // assert: we are not registered for either indications/notifications - let AttAttributeDataChild::GattClientCharacteristicConfiguration(configuration) = resp - else { - unreachable!() - }; assert_eq!( - configuration, + Ok(resp), GattClientCharacteristicConfigurationBuilder { notification: 0, indication: 0 } + .to_vec() ); } @@ -278,11 +271,9 @@ mod test { att_db .write_attribute( handle, - build_view_or_crash(build_att_data(GattClientCharacteristicConfigurationBuilder { - notification: 0, - indication: 1, - })) - .view(), + &GattClientCharacteristicConfigurationBuilder { notification: 0, indication: 1 } + .to_vec() + .unwrap(), ) .await } @@ -301,13 +292,10 @@ mod test { block_on_locally(att_db.read_attribute(SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE)).unwrap(); // assert: we are registered for indications - let AttAttributeDataChild::GattClientCharacteristicConfiguration(configuration) = resp - else { - unreachable!() - }; assert_eq!( - configuration, + Ok(resp), GattClientCharacteristicConfigurationBuilder { notification: 0, indication: 1 } + .to_vec() ); } @@ -321,11 +309,9 @@ mod test { block_on_locally( att_db.write_attribute( SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE, - build_view_or_crash(build_att_data(GattClientCharacteristicConfigurationBuilder { - notification: 0, - indication: 1, - })) - .view(), + &GattClientCharacteristicConfigurationBuilder { notification: 0, indication: 1 } + .to_vec() + .unwrap(), ), ) .unwrap(); @@ -333,11 +319,9 @@ mod test { block_on_locally( att_db.write_attribute( SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE, - build_view_or_crash(build_att_data(GattClientCharacteristicConfigurationBuilder { - notification: 0, - indication: 0, - })) - .view(), + &GattClientCharacteristicConfigurationBuilder { notification: 0, indication: 0 } + .to_vec() + .unwrap(), ), ) .unwrap(); @@ -346,13 +330,10 @@ mod test { block_on_locally(att_db.read_attribute(SERVICE_CHANGE_CCC_DESCRIPTOR_HANDLE)).unwrap(); // assert: we are not registered for indications - let AttAttributeDataChild::GattClientCharacteristicConfiguration(configuration) = resp - else { - unreachable!() - }; assert_eq!( - configuration, + Ok(resp), GattClientCharacteristicConfigurationBuilder { notification: 0, indication: 0 } + .to_vec() ); } diff --git a/system/rust/src/gatt/server/test/test_att_db.rs b/system/rust/src/gatt/server/test/test_att_db.rs index 45b82dcfa9..896f31d4f1 100644 --- a/system/rust/src/gatt/server/test/test_att_db.rs +++ b/system/rust/src/gatt/server/test/test_att_db.rs @@ -3,7 +3,7 @@ use crate::{ ids::AttHandle, server::att_database::{AttAttribute, AttDatabase, StableAttDatabase}, }, - packets::{AttAttributeDataChild, AttAttributeDataView, AttErrorCode}, + packets::AttErrorCode, }; use async_trait::async_trait; @@ -38,10 +38,7 @@ impl TestAttDatabase { #[async_trait(?Send)] impl AttDatabase for TestAttDatabase { - async fn read_attribute( - &self, - handle: AttHandle, - ) -> Result<AttAttributeDataChild, AttErrorCode> { + async fn read_attribute(&self, handle: AttHandle) -> Result<Vec<u8>, AttErrorCode> { info!("reading {handle:?}"); match self.attributes.get(&handle) { Some(TestAttributeWithData { attribute: AttAttribute { permissions, .. }, .. }) @@ -49,17 +46,11 @@ impl AttDatabase for TestAttDatabase { { Err(AttErrorCode::READ_NOT_PERMITTED) } - Some(TestAttributeWithData { data, .. }) => { - Ok(AttAttributeDataChild::RawData(data.borrow().clone().into_boxed_slice())) - } + Some(TestAttributeWithData { data, .. }) => Ok(data.borrow().clone()), None => Err(AttErrorCode::INVALID_HANDLE), } } - async fn write_attribute( - &self, - handle: AttHandle, - data: AttAttributeDataView<'_>, - ) -> Result<(), AttErrorCode> { + async fn write_attribute(&self, handle: AttHandle, data: &[u8]) -> Result<(), AttErrorCode> { match self.attributes.get(&handle) { Some(TestAttributeWithData { attribute: AttAttribute { permissions, .. }, .. }) if !permissions.writable_with_response() => @@ -67,19 +58,19 @@ impl AttDatabase for TestAttDatabase { Err(AttErrorCode::WRITE_NOT_PERMITTED) } Some(TestAttributeWithData { data: data_cell, .. }) => { - data_cell.replace(data.get_raw_payload().collect()); + data_cell.replace(data.to_vec()); Ok(()) } None => Err(AttErrorCode::INVALID_HANDLE), } } - fn write_no_response_attribute(&self, handle: AttHandle, data: AttAttributeDataView<'_>) { + fn write_no_response_attribute(&self, handle: AttHandle, data: &[u8]) { match self.attributes.get(&handle) { Some(TestAttributeWithData { attribute: AttAttribute { permissions, .. }, data: data_cell, }) if !permissions.writable_with_response() => { - data_cell.replace(data.get_raw_payload().collect()); + data_cell.replace(data.to_vec()); } _ => { warn!("rejecting write command to {handle:?}") diff --git a/system/rust/src/gatt/server/transactions/find_by_type_value.rs b/system/rust/src/gatt/server/transactions/find_by_type_value.rs index b09e7f7ef6..5a7cbb280a 100644 --- a/system/rust/src/gatt/server/transactions/find_by_type_value.rs +++ b/system/rust/src/gatt/server/transactions/find_by_type_value.rs @@ -8,7 +8,7 @@ use crate::{ }, packets::{ AttChild, AttErrorCode, AttErrorResponseBuilder, AttFindByTypeValueRequestView, - AttFindByTypeValueResponseBuilder, AttOpcode, AttributeHandleRangeBuilder, Serializable, + AttFindByTypeValueResponseBuilder, AttOpcode, AttributeHandleRangeBuilder, }, }; @@ -43,18 +43,16 @@ pub async fn handle_find_by_type_value_request( continue; } if let Ok(value) = db.read_attribute(handle).await { - if let Ok(data) = value.to_vec() { - if data == request.get_attribute_value().get_raw_payload().collect::<Vec<_>>() { - // match found - if !matches.push(AttributeHandleRangeBuilder { - found_attribute_handle: handle.into(), - group_end_handle: find_group_end(db, attr) - .map(|attr| attr.handle) - .unwrap_or(handle) - .into(), - }) { - break; - } + if value == request.get_attribute_value().get_raw_payload().collect::<Vec<_>>() { + // match found + if !matches.push(AttributeHandleRangeBuilder { + found_attribute_handle: handle.into(), + group_end_handle: find_group_end(db, attr) + .map(|attr| attr.handle) + .unwrap_or(handle) + .into(), + }) { + break; } } } else { diff --git a/system/rust/src/gatt/server/transactions/helpers.rs b/system/rust/src/gatt/server/transactions/helpers.rs index b69547dc99..d868794e30 100644 --- a/system/rust/src/gatt/server/transactions/helpers.rs +++ b/system/rust/src/gatt/server/transactions/helpers.rs @@ -2,4 +2,3 @@ pub mod att_filter_by_size_type; pub mod att_grouping; pub mod att_range_filter; pub mod payload_accumulator; -pub mod truncate_att_data; diff --git a/system/rust/src/gatt/server/transactions/helpers/att_filter_by_size_type.rs b/system/rust/src/gatt/server/transactions/helpers/att_filter_by_size_type.rs index 684e79bf69..52abe8c5c2 100644 --- a/system/rust/src/gatt/server/transactions/helpers/att_filter_by_size_type.rs +++ b/system/rust/src/gatt/server/transactions/helpers/att_filter_by_size_type.rs @@ -4,11 +4,9 @@ use crate::{ core::uuid::Uuid, gatt::server::att_database::{AttAttribute, StableAttDatabase}, - packets::{AttAttributeDataChild, AttErrorCode, Serializable}, + packets::{AttAttributeDataChild, AttErrorCode}, }; -use super::truncate_att_data::truncate_att_data; - /// An attribute and the value #[derive(Debug, PartialEq, Eq)] pub struct AttributeWithValue { @@ -39,9 +37,9 @@ pub async fn filter_read_attributes_by_size_type( for attr @ AttAttribute { handle, .. } in target_attrs { match db.read_attribute(handle).await { - Ok(value) => { - let value = truncate_att_data(value, size_limit); - let value_size = value.size_in_bits().unwrap_or(0); + Ok(mut value) => { + value.truncate(size_limit); + let value_size = value.len(); if let Some(curr_elem_size) = curr_elem_size { if curr_elem_size != value_size { // no more attributes of the same size @@ -51,7 +49,10 @@ pub async fn filter_read_attributes_by_size_type( curr_elem_size = Some(value_size) } - out.push(AttributeWithValue { attr, value }); + out.push(AttributeWithValue { + attr, + value: AttAttributeDataChild::RawData(value.into_boxed_slice()), + }); } Err(err) => { if out.is_empty() { diff --git a/system/rust/src/gatt/server/transactions/helpers/truncate_att_data.rs b/system/rust/src/gatt/server/transactions/helpers/truncate_att_data.rs deleted file mode 100644 index b1a2c3b9de..0000000000 --- a/system/rust/src/gatt/server/transactions/helpers/truncate_att_data.rs +++ /dev/null @@ -1,56 +0,0 @@ -use crate::packets::AttAttributeDataChild; - -pub fn truncate_att_data(data: AttAttributeDataChild, len: usize) -> AttAttributeDataChild { - // Note: we only truncate RawData, not other children - // This behavior is non-ideal, but in practice it's OK - // since anything except for RawData will NEVER exceed an MTU - // Kept since it makes writing tests way easier - match data { - AttAttributeDataChild::RawData(data) => { - let mut data = Vec::from(data); - data.truncate(len); - AttAttributeDataChild::RawData(data.into_boxed_slice()) - } - _ => data, - } -} - -#[cfg(test)] -mod test { - use super::*; - - use crate::packets::{GattServiceDeclarationValueBuilder, Serializable, UuidBuilder}; - - #[test] - fn test_unaffected() { - let data = AttAttributeDataChild::RawData([1, 2, 3].into()); - let mtu = 21; - - let truncated = truncate_att_data(data, mtu); - - assert_eq!(truncated.to_vec().unwrap(), vec![1, 2, 3]); - } - - #[test] - fn test_truncated() { - let data = AttAttributeDataChild::RawData([1, 2, 3].into()); - let mtu = 2; - - let truncated = truncate_att_data(data, mtu); - - assert_eq!(truncated.to_vec().unwrap(), vec![1, 2]); - } - - #[test] - fn test_truncated_non_raw() { - // Verifies that non-Raw data is not truncated - let data = - GattServiceDeclarationValueBuilder { uuid: UuidBuilder { data: [1, 2, 3].into() } } - .into(); - let mtu = 2; - - let truncated = truncate_att_data(data, mtu); - - assert_eq!(truncated.to_vec().unwrap(), vec![1, 2, 3]); - } -} diff --git a/system/rust/src/gatt/server/transactions/read_request.rs b/system/rust/src/gatt/server/transactions/read_request.rs index 4cb517764b..fb33074c6d 100644 --- a/system/rust/src/gatt/server/transactions/read_request.rs +++ b/system/rust/src/gatt/server/transactions/read_request.rs @@ -1,13 +1,11 @@ use crate::{ gatt::server::att_database::AttDatabase, packets::{ - AttAttributeDataBuilder, AttChild, AttErrorResponseBuilder, AttOpcode, AttReadRequestView, - AttReadResponseBuilder, + AttAttributeDataBuilder, AttAttributeDataChild, AttChild, AttErrorResponseBuilder, + AttOpcode, AttReadRequestView, AttReadResponseBuilder, }, }; -use super::helpers::truncate_att_data::truncate_att_data; - pub async fn handle_read_request<T: AttDatabase>( request: AttReadRequestView<'_>, mtu: usize, @@ -16,11 +14,16 @@ pub async fn handle_read_request<T: AttDatabase>( let handle = request.get_attribute_handle().into(); match db.read_attribute(handle).await { - Ok(data) => AttReadResponseBuilder { + Ok(mut data) => { // as per 5.3 3F 3.4.4.4 ATT_READ_RSP, we truncate to MTU - 1 - value: AttAttributeDataBuilder { _child_: truncate_att_data(data, mtu - 1) }, + data.truncate(mtu - 1); + AttReadResponseBuilder { + value: AttAttributeDataBuilder { + _child_: AttAttributeDataChild::RawData(data.into_boxed_slice()), + }, + } + .into() } - .into(), Err(error_code) => AttErrorResponseBuilder { opcode_in_error: AttOpcode::READ_REQUEST, handle_in_error: handle.into(), diff --git a/system/rust/src/gatt/server/transactions/write_request.rs b/system/rust/src/gatt/server/transactions/write_request.rs index 325b9b7373..23a11d9d56 100644 --- a/system/rust/src/gatt/server/transactions/write_request.rs +++ b/system/rust/src/gatt/server/transactions/write_request.rs @@ -10,7 +10,8 @@ pub async fn handle_write_request<T: AttDatabase>( db: &T, ) -> AttChild { let handle = request.get_handle().into(); - match db.write_attribute(handle, request.get_value()).await { + let value = request.get_value().get_raw_payload().collect::<Vec<_>>(); + match db.write_attribute(handle, &value).await { Ok(()) => AttWriteResponseBuilder {}.into(), Err(error_code) => AttErrorResponseBuilder { opcode_in_error: AttOpcode::WRITE_REQUEST, @@ -38,8 +39,8 @@ mod test { }, }, packets::{ - AttAttributeDataChild, AttChild, AttErrorCode, AttErrorResponseBuilder, - AttWriteRequestBuilder, AttWriteResponseBuilder, + AttAttributeDataBuilder, AttAttributeDataChild, AttChild, AttErrorCode, + AttErrorResponseBuilder, AttWriteRequestBuilder, AttWriteResponseBuilder, }, utils::packet::{build_att_data, build_view_or_crash}, }; @@ -55,12 +56,14 @@ mod test { }, vec![], )]); - let data = AttAttributeDataChild::RawData([1, 2].into()); + let data = vec![1, 2]; // act: write to the attribute let att_view = build_view_or_crash(AttWriteRequestBuilder { handle: AttHandle(1).into(), - value: build_att_data(data.clone()), + value: AttAttributeDataBuilder { + _child_: AttAttributeDataChild::RawData(data.clone().into_boxed_slice()), + }, }); let resp = block_on(handle_write_request(att_view.view(), &db)); diff --git a/system/rust/src/packets.rs b/system/rust/src/packets.rs index db0fcf6b20..a14103f1f7 100644 --- a/system/rust/src/packets.rs +++ b/system/rust/src/packets.rs @@ -7,3 +7,9 @@ #![feature(mixed_integer_ops)] include!(concat!(env!("OUT_DIR"), "/_packets.rs")); + +impl std::cmp::PartialEq for SerializeError { + fn eq(&self, rhs: &Self) -> bool { + std::mem::discriminant(self) == std::mem::discriminant(rhs) + } +} diff --git a/system/rust/tests/gatt_callbacks_test.rs b/system/rust/tests/gatt_callbacks_test.rs index 9ba62a5946..1a462da113 100644 --- a/system/rust/tests/gatt_callbacks_test.rs +++ b/system/rust/tests/gatt_callbacks_test.rs @@ -12,8 +12,7 @@ use bluetooth_core::{ ids::{AttHandle, ConnectionId, ServerId, TransactionId, TransportIndex}, mocks::mock_callbacks::{MockCallbackEvents, MockCallbacks}, }, - packets::{AttAttributeDataChild, AttErrorCode, Packet}, - utils::packet::{build_att_data, build_view_or_crash}, + packets::AttErrorCode, }; use tokio::{sync::mpsc::UnboundedReceiver, task::spawn_local, time::Instant}; use utils::start_test; @@ -73,7 +72,7 @@ fn test_read_characteristic_response() { start_test(async { // arrange let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); - let data = Ok(AttAttributeDataChild::RawData([1, 2].into())); + let data = [1, 2]; // act: start read operation let datastore = callback_manager.get_datastore(SERVER_ID); @@ -83,10 +82,10 @@ fn test_read_characteristic_response() { ); // provide a response let trans_id = pull_trans_id(&mut callbacks_rx).await; - callback_manager.send_response(CONN_ID, trans_id, data.clone()).unwrap(); + callback_manager.send_response(CONN_ID, trans_id, Ok(data.to_vec())).unwrap(); // assert: that the supplied data was correctly read - assert_eq!(pending_read.await.unwrap(), data); + assert_eq!(pending_read.await.unwrap(), Ok(data.to_vec())); }); } @@ -95,8 +94,8 @@ fn test_sequential_reads() { start_test(async { // arrange let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); - let data1 = Ok(AttAttributeDataChild::RawData([1, 2].into())); - let data2 = Ok(AttAttributeDataChild::RawData([3, 4].into())); + let data1 = [1, 2]; + let data2 = [3, 4]; // act: start read operation let datastore = callback_manager.get_datastore(SERVER_ID); @@ -106,7 +105,7 @@ fn test_sequential_reads() { ); // respond to first let trans_id = pull_trans_id(&mut callbacks_rx).await; - callback_manager.send_response(CONN_ID, trans_id, data1.clone()).unwrap(); + callback_manager.send_response(CONN_ID, trans_id, Ok(data1.to_vec())).unwrap(); // do a second read operation let datastore = callback_manager.get_datastore(SERVER_ID); @@ -116,11 +115,11 @@ fn test_sequential_reads() { ); // respond to second let trans_id = pull_trans_id(&mut callbacks_rx).await; - callback_manager.send_response(CONN_ID, trans_id, data2.clone()).unwrap(); + callback_manager.send_response(CONN_ID, trans_id, Ok(data2.to_vec())).unwrap(); // assert: that both operations got the correct response - assert_eq!(pending_read_1.await.unwrap(), data1); - assert_eq!(pending_read_2.await.unwrap(), data2); + assert_eq!(pending_read_1.await.unwrap(), Ok(data1.to_vec())); + assert_eq!(pending_read_2.await.unwrap(), Ok(data2.to_vec())); }); } @@ -129,8 +128,8 @@ fn test_concurrent_reads() { start_test(async { // arrange let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); - let data1 = Ok(AttAttributeDataChild::RawData([1, 2].into())); - let data2 = Ok(AttAttributeDataChild::RawData([3, 4].into())); + let data1 = [1, 2]; + let data2 = [3, 4]; // act: start read operation let datastore = callback_manager.get_datastore(SERVER_ID); @@ -148,15 +147,15 @@ fn test_concurrent_reads() { // respond to first let trans_id = pull_trans_id(&mut callbacks_rx).await; - callback_manager.send_response(CONN_ID, trans_id, data1.clone()).unwrap(); + callback_manager.send_response(CONN_ID, trans_id, Ok(data1.to_vec())).unwrap(); // respond to second let trans_id = pull_trans_id(&mut callbacks_rx).await; - callback_manager.send_response(CONN_ID, trans_id, data2.clone()).unwrap(); + callback_manager.send_response(CONN_ID, trans_id, Ok(data2.to_vec())).unwrap(); // assert: that both operations got the correct response - assert_eq!(pending_read_1.await.unwrap(), data1); - assert_eq!(pending_read_2.await.unwrap(), data2); + assert_eq!(pending_read_1.await.unwrap(), Ok(data1.to_vec())); + assert_eq!(pending_read_2.await.unwrap(), Ok(data2.to_vec())); }); } @@ -186,7 +185,7 @@ fn test_invalid_trans_id() { start_test(async { // arrange let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); - let data = Ok(AttAttributeDataChild::RawData([1, 2].into())); + let data = [1, 2]; // act: start a read operation let datastore = callback_manager.get_datastore(SERVER_ID); @@ -194,7 +193,9 @@ fn test_invalid_trans_id() { // 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); - let err = callback_manager.send_response(CONN_ID, invalid_trans_id, data).unwrap_err(); + let err = callback_manager + .send_response(CONN_ID, invalid_trans_id, Ok(data.to_vec())) + .unwrap_err(); // assert assert_eq!(err, CallbackResponseError::NonExistentTransaction(invalid_trans_id)); @@ -206,7 +207,7 @@ 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())); + let data = [1, 2]; // act: start a read operation let datastore = callback_manager.get_datastore(SERVER_ID); @@ -214,7 +215,9 @@ fn test_invalid_conn_id() { // 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(); + let err = callback_manager + .send_response(invalid_conn_id, trans_id, Ok(data.to_vec())) + .unwrap_err(); // assert assert_eq!(err, CallbackResponseError::NonExistentTransaction(trans_id)); @@ -228,13 +231,11 @@ fn test_write_characteristic_callback() { let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); // act: start write operation - let data = - build_view_or_crash(build_att_data(AttAttributeDataChild::RawData([1, 2].into()))); - let cloned_data = data.view().to_owned_packet(); + let data = [1, 2]; spawn_local(async move { callback_manager .get_datastore(SERVER_ID) - .write(TCB_IDX, HANDLE_1, BACKING_TYPE, WRITE_REQUEST_TYPE, cloned_data.view()) + .write(TCB_IDX, HANDLE_1, BACKING_TYPE, WRITE_REQUEST_TYPE, &data) .await }); @@ -250,10 +251,7 @@ fn test_write_characteristic_callback() { else { unreachable!() }; - assert_eq!( - recv_data.view().get_raw_payload().collect::<Vec<_>>(), - data.view().get_raw_payload().collect::<Vec<_>>() - ); + assert_eq!(recv_data, data); }); } @@ -264,12 +262,11 @@ fn test_write_characteristic_response() { let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); // act: start write operation - let data = - build_view_or_crash(build_att_data(AttAttributeDataChild::RawData([1, 2].into()))); + let data = [1, 2]; let datastore = callback_manager.get_datastore(SERVER_ID); let pending_write = spawn_local(async move { datastore - .write(TCB_IDX, HANDLE_1, BACKING_TYPE, GattWriteRequestType::Request, data.view()) + .write(TCB_IDX, HANDLE_1, BACKING_TYPE, GattWriteRequestType::Request, &data) .await }); // provide a response with some error code @@ -361,13 +358,12 @@ fn test_write_no_response_callback() { let (callback_manager, mut callbacks_rx) = initialize_manager_with_connection(); // act: start write_no_response operation - let data = - build_view_or_crash(build_att_data(AttAttributeDataChild::RawData([1, 2].into()))); + let data = [1, 2]; callback_manager.get_datastore(SERVER_ID).write_no_response( TCB_IDX, HANDLE_1, BACKING_TYPE, - data.view(), + &data, ); // assert: verify the write callback is received @@ -382,10 +378,7 @@ fn test_write_no_response_callback() { else { unreachable!() }; - assert_eq!( - recv_data.view().get_raw_payload().collect::<Vec<_>>(), - data.view().get_raw_payload().collect::<Vec<_>>() - ); + assert_eq!(recv_data, data); }); } diff --git a/system/rust/tests/gatt_server_test.rs b/system/rust/tests/gatt_server_test.rs index 8aae62105a..2b31db764c 100644 --- a/system/rust/tests/gatt_server_test.rs +++ b/system/rust/tests/gatt_server_test.rs @@ -35,9 +35,9 @@ use bluetooth_core::{ AttFindInformationResponseChild, AttHandleValueConfirmationBuilder, AttHandleValueIndicationBuilder, AttOpcode, AttReadByTypeRequestBuilder, AttReadRequestBuilder, AttReadResponseBuilder, AttWriteRequestBuilder, - AttWriteResponseBuilder, GattClientCharacteristicConfigurationBuilder, - GattServiceChangedBuilder, GattServiceDeclarationValueBuilder, Serializable, - UuidAsAttDataBuilder, + AttWriteResponseBuilder, GattCharacteristicDeclarationValueView, + GattClientCharacteristicConfigurationBuilder, GattServiceChangedBuilder, + GattServiceDeclarationValueBuilder, Packet, Serializable, UuidAsAttDataBuilder, }, utils::packet::{build_att_data, build_att_view_or_crash}, }; @@ -129,7 +129,7 @@ fn test_service_read() { // assert assert_eq!(tcb_idx, TCB_IDX); assert_eq!( - resp, + resp.to_vec(), AttBuilder { opcode: AttOpcode::READ_RESPONSE, _child_: AttReadResponseBuilder { @@ -139,6 +139,7 @@ fn test_service_read() { } .into() } + .to_vec() ); }) } @@ -204,7 +205,7 @@ fn test_characteristic_read() { } else { unreachable!() }; - tx.send(Ok(data.clone())).unwrap(); + tx.send(Ok(DATA.to_vec())).unwrap(); let (tcb_idx, resp) = transport_rx.recv().await.unwrap(); // assert @@ -261,10 +262,7 @@ fn test_characteristic_write() { _child_: AttWriteResponseBuilder {}.into() } ); - assert_eq!( - data.to_vec().unwrap(), - written_data.view().get_raw_payload().collect::<Vec<_>>() - ) + assert_eq!(data.to_vec().unwrap(), written_data) }) } @@ -372,10 +370,7 @@ fn test_write_to_descriptor() { _child_: AttWriteResponseBuilder {}.into() } ); - assert_eq!( - data.to_vec().unwrap(), - written_data.view().get_raw_payload().collect::<Vec<_>>() - ) + assert_eq!(data.to_vec().unwrap(), written_data) }) } @@ -384,8 +379,6 @@ fn test_multiple_servers() { start_test(async move { // arrange let (mut gatt, mut transport_rx) = start_gatt_module(); - let data = AttAttributeDataChild::RawData(DATA.into()); - let another_data = AttAttributeDataChild::RawData(ANOTHER_DATA.into()); // open the default server (SERVER_ID on CONN_ID) let mut data_rx_1 = create_server_and_open_connection(&mut gatt); // open a second server and connect to it (ANOTHER_SERVER_ID on ANOTHER_CONN_ID) @@ -427,13 +420,13 @@ fn test_multiple_servers() { let MockDatastoreEvents::Read(TCB_IDX, _, _, tx) = data_rx_1.recv().await.unwrap() else { unreachable!() }; - tx.send(Ok(data.clone())).unwrap(); + tx.send(Ok(DATA.to_vec())).unwrap(); // and then the second read with `another_data` let MockDatastoreEvents::Read(ANOTHER_TCB_IDX, _, _, tx) = data_rx_2.recv().await.unwrap() else { unreachable!() }; - tx.send(Ok(another_data.clone())).unwrap(); + tx.send(Ok(ANOTHER_DATA.to_vec())).unwrap(); // receive both response packets let (tcb_idx_1, resp_1) = transport_rx.recv().await.unwrap(); @@ -540,18 +533,18 @@ fn test_service_change_indication() { else { unreachable!() }; - let service_change_char_handle = resp + let service_change_char_handle: AttHandle = resp .data .into_vec() .into_iter() .find_map(|characteristic| { - let AttAttributeDataChild::GattCharacteristicDeclarationValue(decl) = - characteristic.value._child_ - else { - unreachable!(); - }; - if decl.uuid == SERVICE_CHANGE_UUID.into() { - Some(decl.handle) + let value = characteristic.value.to_vec().unwrap(); + let decl = + GattCharacteristicDeclarationValueView::try_parse_from_buffer(value.as_slice()) + .unwrap(); + + if SERVICE_CHANGE_UUID == decl.get_uuid().try_into().unwrap() { + Some(decl.get_handle().into()) } else { None } @@ -560,7 +553,7 @@ fn test_service_change_indication() { // act: find the CCC descriptor for the service changed characteristic gatt.get_bearer(TCB_IDX).unwrap().handle_packet( build_att_view_or_crash(AttFindInformationRequestBuilder { - starting_handle: service_change_char_handle.clone(), + starting_handle: service_change_char_handle.into(), ending_handle: AttHandle::MAX.into(), }) .view(), @@ -619,7 +612,7 @@ fn test_service_change_indication() { else { unreachable!() }; - assert_eq!(indication.handle, service_change_char_handle); + assert_eq!(indication.handle, service_change_char_handle.into()); assert_eq!( indication.value, build_att_data(GattServiceChangedBuilder { |