Loading system/rust/Android.bp +3 −1 Original line number Diff line number Diff line Loading @@ -36,8 +36,10 @@ rust_defaults { "libbitflags", "libbt_common", "libbt_shim", "libbytes", "libcxx", "liblog_rust", "libpdl_runtime", "libscopeguard", ], whole_static_libs: [ Loading Loading @@ -193,7 +195,7 @@ gensrcs { genrule { name: "bluetooth_core_rust_packets", defaults: ["pdl_rust_noalloc_generator_defaults"], defaults: ["pdl_rust_generator_defaults"], srcs: ["src/packets.pdl"], out: ["_packets.rs"], } system/rust/Cargo.toml +3 −2 Original line number Diff line number Diff line Loading @@ -31,13 +31,14 @@ android_logger = "*" jni = "*" paste = "*" async-trait = "*" pdl-runtime = "0.3.0" pdl-runtime = "0.3.1" tokio-test = "0.4.2" tokio = { version = "1.23.0", features = ["macros"] } scopeguard = "1.1.0" bytes = "1.5.0" [build-dependencies] pdl-compiler = "0.3.0" pdl-compiler = "0.3.1" [lib] crate-type = ["rlib"] Loading system/rust/build.rs +1 −3 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ //! //! Run `cargo install --path .` in `external/rust/crates/pdl-compiler` to ensure `pdlc` //! is in your path. use pdl_compiler; use std::{env, fs::File, io::Write, path::Path}; fn main() { Loading @@ -13,9 +12,8 @@ fn main() { let mut sources = pdl_compiler::ast::SourceDatabase::new(); let file = pdl_compiler::parser::parse_file(&mut sources, "src/packets.pdl") .expect("failed to parse input pdl file"); let schema = pdl_compiler::backends::intermediate::generate(&file).unwrap(); let generated = pdl_compiler::backends::rust_no_allocation::generate(&file, &schema).unwrap(); let generated = pdl_compiler::backends::rust::generate(&sources, &file, &[]); dest_file.write_all(generated.as_bytes()).unwrap(); println!("cargo:rerun-if-changed=build.rs"); Loading system/rust/src/core/uuid.rs +30 −47 Original line number Diff line number Diff line //! A UUID (See Core Spec 5.3 Vol 1E 2.9.1. Basic Types) use crate::packets::{ ParseError, Uuid128Builder, Uuid128View, Uuid16Builder, Uuid16View, UuidBuilder, UuidView, }; use crate::packets::att; /// A UUID (See Core Spec 5.3 Vol 1E 2.9.1. Basic Types) /// Loading Loading @@ -33,83 +31,74 @@ impl Uuid { } } impl TryFrom<UuidView<'_>> for Uuid { type Error = ParseError; impl TryFrom<att::Uuid> for Uuid { type Error = att::Uuid; fn try_from(value: UuidView<'_>) -> Result<Self, ParseError> { let bytes = value.get_data_iter().collect::<Vec<_>>(); fn try_from(value: att::Uuid) -> Result<Self, att::Uuid> { let bytes = value.data.as_slice(); Ok(match bytes.len() { 2 => Self::new(u16::from_le_bytes([bytes[0], bytes[1]]) as u32), 4 => Self::new(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])), // TODO(aryarahul) - should we handle >16 byte Uuids and drop extra bytes? _ => Self::new_from_le_bytes( bytes.try_into().map_err(|_| ParseError::OutOfBoundsAccess)?, ), _ => Self::new_from_le_bytes(bytes.try_into().map_err(|_| value)?), }) } } impl From<Uuid16View<'_>> for Uuid { fn from(uuid: Uuid16View) -> Self { Self::new(uuid.get_data() as u32) impl From<att::Uuid16> for Uuid { fn from(uuid: att::Uuid16) -> Self { Self::new(uuid.data as u32) } } impl From<Uuid128View<'_>> for Uuid { fn from(uuid: Uuid128View) -> Self { Self::new_from_le_bytes( uuid.get_data_iter() .collect::<Vec<_>>() .try_into() .expect("Uuid128View MUST have exactly 16 bytes"), ) impl From<att::Uuid128> for Uuid { fn from(uuid: att::Uuid128) -> Self { Self::new_from_le_bytes(uuid.data) } } impl From<Uuid> for UuidBuilder { impl From<Uuid> for att::Uuid { fn from(value: Uuid) -> Self { // TODO(aryarahul): compress to UUID-16 if possible UuidBuilder { data: value.le_bytes().into_iter().collect() } att::Uuid { data: value.le_bytes().to_vec() } } } impl TryFrom<Uuid> for Uuid16Builder { impl TryFrom<Uuid> for att::Uuid16 { type Error = Uuid; fn try_from(value: Uuid) -> Result<Self, Self::Error> { let backing = u128::from_be_bytes(value.0); if backing & ((1u128 << 96) - 1) == BASE_UUID { if let Ok(data) = u16::try_from(backing >> 96) { return Ok(Uuid16Builder { data }); return Ok(att::Uuid16 { data }); } } Err(value) } } impl From<Uuid> for Uuid128Builder { impl From<Uuid> for att::Uuid128 { fn from(value: Uuid) -> Self { Uuid128Builder { data: value.le_bytes().to_vec().into() } att::Uuid128 { data: value.le_bytes() } } } #[cfg(test)] mod test { use crate::utils::packet::build_view_or_crash; use super::*; #[test] fn test_uuid16_builder_successful() { let uuid = Uuid::new(0x0102); let builder: Uuid16Builder = uuid.try_into().unwrap(); let builder: att::Uuid16 = uuid.try_into().unwrap(); assert_eq!(builder.data, 0x0102); } #[test] fn test_uuid16_builder_fail_nonzero_trailing_bytes() { let uuid = Uuid::new(0x01020304); let res: Result<Uuid16Builder, _> = uuid.try_into(); let res: Result<att::Uuid16, _> = uuid.try_into(); assert!(res.is_err()); } Loading @@ -118,14 +107,14 @@ mod test { let mut uuid = Uuid::new(0x0102); uuid.0[0] = 1; let res: Result<Uuid16Builder, _> = uuid.try_into(); let res: Result<att::Uuid16, _> = uuid.try_into(); assert!(res.is_err()); } #[test] fn test_uuid128_builder() { let uuid = Uuid::new(0x01020304); let builder: Uuid128Builder = uuid.into(); let builder: att::Uuid128 = uuid.into(); assert_eq!(builder.data[..12], BASE_UUID.to_le_bytes()[..12]); assert_eq!(builder.data[12..], [4, 3, 2, 1]); } Loading @@ -133,7 +122,7 @@ mod test { #[test] fn test_uuid_builder() { let uuid = Uuid::new(0x01020304); let builder: UuidBuilder = uuid.into(); let builder: att::Uuid = uuid.into(); assert_eq!(builder.data[..12], BASE_UUID.to_le_bytes()[..12]); assert_eq!(builder.data[12..], [4, 3, 2, 1]); } Loading @@ -141,7 +130,7 @@ mod test { #[test] fn test_uuid_from_16_fixed_view() { let expected = Uuid::new(0x0102); let actual: Uuid = build_view_or_crash(Uuid16Builder { data: 0x0102 }).view().into(); let actual: Uuid = att::Uuid16 { data: 0x0102 }.try_into().unwrap(); assert_eq!(expected, actual); } Loading @@ -149,25 +138,21 @@ mod test { fn test_uuid_from_128_fixed_view() { let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let expected = Uuid::new_from_le_bytes(data); let actual: Uuid = build_view_or_crash(Uuid128Builder { data: data.into() }).view().into(); let actual: Uuid = att::Uuid128 { data }.try_into().unwrap(); assert_eq!(expected, actual); } #[test] fn test_uuid_from_16_view() { let expected = Uuid::new(0x0102); let actual: Uuid = build_view_or_crash(UuidBuilder { data: [2, 1].into() }).view().try_into().unwrap(); let actual: Uuid = att::Uuid { data: vec![2, 1] }.try_into().unwrap(); assert_eq!(expected, actual); } #[test] fn test_uuid_from_32_view() { let expected = Uuid::new(0x01020304); let actual: Uuid = build_view_or_crash(UuidBuilder { data: [4, 3, 2, 1].into() }) .view() .try_into() .unwrap(); let actual: Uuid = att::Uuid { data: vec![4, 3, 2, 1] }.try_into().unwrap(); assert_eq!(expected, actual); } Loading @@ -175,16 +160,14 @@ mod test { fn test_uuid_from_128_view() { let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let expected = Uuid::new_from_le_bytes(data); let actual: Uuid = build_view_or_crash(UuidBuilder { data: data.into() }).view().try_into().unwrap(); let actual: Uuid = att::Uuid { data: data.into() }.try_into().unwrap(); assert_eq!(expected, actual); } #[test] fn test_uuid_from_invalid_view() { let packet = build_view_or_crash(UuidBuilder { data: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1].into() }); let res = Uuid::try_from(packet.view()); let packet = att::Uuid { data: vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }; let res = Uuid::try_from(packet); assert!(res.is_err()); } } system/rust/src/gatt/arbiter.rs +23 −36 Original line number Diff line number Diff line //! This module handles "arbitration" of ATT packets, to determine whether they //! should be handled by the primary stack or by the Rust stack use pdl_runtime::Packet; use std::sync::{Arc, Mutex}; use log::{error, trace, warn}; use std::sync::RwLock; use crate::{ do_in_rust_thread, packets::{AttOpcode, OwnedAttView, OwnedPacket}, }; use crate::{do_in_rust_thread, packets::att}; use super::{ ffi::{InterceptAction, StoreCallbacksFromRust}, Loading Loading @@ -62,19 +60,19 @@ pub fn has_arbiter() -> bool { fn try_parse_att_server_packet( isolation_manager: &IsolationManager, tcb_idx: TransportIndex, packet: Box<[u8]>, ) -> Option<OwnedAttView> { packet: &[u8], ) -> Option<att::Att> { isolation_manager.get_server_id(tcb_idx)?; let att = OwnedAttView::try_parse(packet).ok()?; let att = att::Att::decode_full(packet).ok()?; if att.view().get_opcode() == AttOpcode::EXCHANGE_MTU_REQUEST { if att.opcode == att::AttOpcode::ExchangeMtuRequest { // special case: this server opcode is handled by legacy stack, and we snoop // on its handling, since the MTU is shared between the client + server return None; } match classify_opcode(att.view().get_opcode()) { match classify_opcode(att.opcode) { OperationType::Command | OperationType::Request | OperationType::Confirmation => Some(att), _ => None, } Loading Loading @@ -123,13 +121,13 @@ fn intercept_packet(tcb_idx: u8, packet: Vec<u8>) -> InterceptAction { } let tcb_idx = TransportIndex(tcb_idx); if let Some(att) = with_arbiter(|arbiter| { try_parse_att_server_packet(arbiter, tcb_idx, packet.into_boxed_slice()) }) { if let Some(att) = with_arbiter(|arbiter| try_parse_att_server_packet(arbiter, tcb_idx, &packet)) { do_in_rust_thread(move |modules| { trace!("pushing packet to GATT"); if let Some(bearer) = modules.gatt_module.get_bearer(tcb_idx) { bearer.handle_packet(att.view()) bearer.handle_packet(att) } else { error!("Bearer for {tcb_idx:?} not found"); } Loading Loading @@ -160,10 +158,7 @@ mod test { use crate::{ gatt::ids::{AttHandle, ServerId}, packets::{ AttBuilder, AttExchangeMtuRequestBuilder, AttOpcode, AttReadRequestBuilder, Serializable, }, packets::att, }; const TCB_IDX: TransportIndex = TransportIndex(1); Loading @@ -183,15 +178,12 @@ mod test { #[test] fn test_packet_capture_when_isolated() { let isolation_manager = create_manager_with_isolated_connection(TCB_IDX, SERVER_ID); let packet = AttBuilder { opcode: AttOpcode::READ_REQUEST, _child_: AttReadRequestBuilder { attribute_handle: AttHandle(1).into() }.into(), }; let packet = att::AttReadRequest { attribute_handle: AttHandle(1).into() }; let out = try_parse_att_server_packet( &isolation_manager, TCB_IDX, packet.to_vec().unwrap().into(), &packet.encode_to_vec().unwrap(), ); assert!(out.is_some()); Loading @@ -200,15 +192,16 @@ mod test { #[test] fn test_packet_bypass_when_isolated() { let isolation_manager = create_manager_with_isolated_connection(TCB_IDX, SERVER_ID); let packet = AttBuilder { opcode: AttOpcode::ERROR_RESPONSE, _child_: AttReadRequestBuilder { attribute_handle: AttHandle(1).into() }.into(), let packet = att::AttErrorResponse { opcode_in_error: att::AttOpcode::ReadResponse, handle_in_error: AttHandle(1).into(), error_code: att::AttErrorCode::InvalidHandle, }; let out = try_parse_att_server_packet( &isolation_manager, TCB_IDX, packet.to_vec().unwrap().into(), &packet.encode_to_vec().unwrap(), ); assert!(out.is_none()); Loading @@ -217,15 +210,12 @@ mod test { #[test] fn test_mtu_bypass() { let isolation_manager = create_manager_with_isolated_connection(TCB_IDX, SERVER_ID); let packet = AttBuilder { opcode: AttOpcode::EXCHANGE_MTU_REQUEST, _child_: AttExchangeMtuRequestBuilder { mtu: 64 }.into(), }; let packet = att::AttExchangeMtuRequest { mtu: 64 }; let out = try_parse_att_server_packet( &isolation_manager, TCB_IDX, packet.to_vec().unwrap().into(), &packet.encode_to_vec().unwrap(), ); assert!(out.is_none()); Loading @@ -234,15 +224,12 @@ mod test { #[test] fn test_packet_bypass_when_not_isolated() { let isolation_manager = IsolationManager::new(); let packet = AttBuilder { opcode: AttOpcode::READ_REQUEST, _child_: AttReadRequestBuilder { attribute_handle: AttHandle(1).into() }.into(), }; let packet = att::AttReadRequest { attribute_handle: AttHandle(1).into() }; let out = try_parse_att_server_packet( &isolation_manager, TCB_IDX, packet.to_vec().unwrap().into(), &packet.encode_to_vec().unwrap(), ); assert!(out.is_none()); Loading Loading
system/rust/Android.bp +3 −1 Original line number Diff line number Diff line Loading @@ -36,8 +36,10 @@ rust_defaults { "libbitflags", "libbt_common", "libbt_shim", "libbytes", "libcxx", "liblog_rust", "libpdl_runtime", "libscopeguard", ], whole_static_libs: [ Loading Loading @@ -193,7 +195,7 @@ gensrcs { genrule { name: "bluetooth_core_rust_packets", defaults: ["pdl_rust_noalloc_generator_defaults"], defaults: ["pdl_rust_generator_defaults"], srcs: ["src/packets.pdl"], out: ["_packets.rs"], }
system/rust/Cargo.toml +3 −2 Original line number Diff line number Diff line Loading @@ -31,13 +31,14 @@ android_logger = "*" jni = "*" paste = "*" async-trait = "*" pdl-runtime = "0.3.0" pdl-runtime = "0.3.1" tokio-test = "0.4.2" tokio = { version = "1.23.0", features = ["macros"] } scopeguard = "1.1.0" bytes = "1.5.0" [build-dependencies] pdl-compiler = "0.3.0" pdl-compiler = "0.3.1" [lib] crate-type = ["rlib"] Loading
system/rust/build.rs +1 −3 Original line number Diff line number Diff line Loading @@ -2,7 +2,6 @@ //! //! Run `cargo install --path .` in `external/rust/crates/pdl-compiler` to ensure `pdlc` //! is in your path. use pdl_compiler; use std::{env, fs::File, io::Write, path::Path}; fn main() { Loading @@ -13,9 +12,8 @@ fn main() { let mut sources = pdl_compiler::ast::SourceDatabase::new(); let file = pdl_compiler::parser::parse_file(&mut sources, "src/packets.pdl") .expect("failed to parse input pdl file"); let schema = pdl_compiler::backends::intermediate::generate(&file).unwrap(); let generated = pdl_compiler::backends::rust_no_allocation::generate(&file, &schema).unwrap(); let generated = pdl_compiler::backends::rust::generate(&sources, &file, &[]); dest_file.write_all(generated.as_bytes()).unwrap(); println!("cargo:rerun-if-changed=build.rs"); Loading
system/rust/src/core/uuid.rs +30 −47 Original line number Diff line number Diff line //! A UUID (See Core Spec 5.3 Vol 1E 2.9.1. Basic Types) use crate::packets::{ ParseError, Uuid128Builder, Uuid128View, Uuid16Builder, Uuid16View, UuidBuilder, UuidView, }; use crate::packets::att; /// A UUID (See Core Spec 5.3 Vol 1E 2.9.1. Basic Types) /// Loading Loading @@ -33,83 +31,74 @@ impl Uuid { } } impl TryFrom<UuidView<'_>> for Uuid { type Error = ParseError; impl TryFrom<att::Uuid> for Uuid { type Error = att::Uuid; fn try_from(value: UuidView<'_>) -> Result<Self, ParseError> { let bytes = value.get_data_iter().collect::<Vec<_>>(); fn try_from(value: att::Uuid) -> Result<Self, att::Uuid> { let bytes = value.data.as_slice(); Ok(match bytes.len() { 2 => Self::new(u16::from_le_bytes([bytes[0], bytes[1]]) as u32), 4 => Self::new(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]])), // TODO(aryarahul) - should we handle >16 byte Uuids and drop extra bytes? _ => Self::new_from_le_bytes( bytes.try_into().map_err(|_| ParseError::OutOfBoundsAccess)?, ), _ => Self::new_from_le_bytes(bytes.try_into().map_err(|_| value)?), }) } } impl From<Uuid16View<'_>> for Uuid { fn from(uuid: Uuid16View) -> Self { Self::new(uuid.get_data() as u32) impl From<att::Uuid16> for Uuid { fn from(uuid: att::Uuid16) -> Self { Self::new(uuid.data as u32) } } impl From<Uuid128View<'_>> for Uuid { fn from(uuid: Uuid128View) -> Self { Self::new_from_le_bytes( uuid.get_data_iter() .collect::<Vec<_>>() .try_into() .expect("Uuid128View MUST have exactly 16 bytes"), ) impl From<att::Uuid128> for Uuid { fn from(uuid: att::Uuid128) -> Self { Self::new_from_le_bytes(uuid.data) } } impl From<Uuid> for UuidBuilder { impl From<Uuid> for att::Uuid { fn from(value: Uuid) -> Self { // TODO(aryarahul): compress to UUID-16 if possible UuidBuilder { data: value.le_bytes().into_iter().collect() } att::Uuid { data: value.le_bytes().to_vec() } } } impl TryFrom<Uuid> for Uuid16Builder { impl TryFrom<Uuid> for att::Uuid16 { type Error = Uuid; fn try_from(value: Uuid) -> Result<Self, Self::Error> { let backing = u128::from_be_bytes(value.0); if backing & ((1u128 << 96) - 1) == BASE_UUID { if let Ok(data) = u16::try_from(backing >> 96) { return Ok(Uuid16Builder { data }); return Ok(att::Uuid16 { data }); } } Err(value) } } impl From<Uuid> for Uuid128Builder { impl From<Uuid> for att::Uuid128 { fn from(value: Uuid) -> Self { Uuid128Builder { data: value.le_bytes().to_vec().into() } att::Uuid128 { data: value.le_bytes() } } } #[cfg(test)] mod test { use crate::utils::packet::build_view_or_crash; use super::*; #[test] fn test_uuid16_builder_successful() { let uuid = Uuid::new(0x0102); let builder: Uuid16Builder = uuid.try_into().unwrap(); let builder: att::Uuid16 = uuid.try_into().unwrap(); assert_eq!(builder.data, 0x0102); } #[test] fn test_uuid16_builder_fail_nonzero_trailing_bytes() { let uuid = Uuid::new(0x01020304); let res: Result<Uuid16Builder, _> = uuid.try_into(); let res: Result<att::Uuid16, _> = uuid.try_into(); assert!(res.is_err()); } Loading @@ -118,14 +107,14 @@ mod test { let mut uuid = Uuid::new(0x0102); uuid.0[0] = 1; let res: Result<Uuid16Builder, _> = uuid.try_into(); let res: Result<att::Uuid16, _> = uuid.try_into(); assert!(res.is_err()); } #[test] fn test_uuid128_builder() { let uuid = Uuid::new(0x01020304); let builder: Uuid128Builder = uuid.into(); let builder: att::Uuid128 = uuid.into(); assert_eq!(builder.data[..12], BASE_UUID.to_le_bytes()[..12]); assert_eq!(builder.data[12..], [4, 3, 2, 1]); } Loading @@ -133,7 +122,7 @@ mod test { #[test] fn test_uuid_builder() { let uuid = Uuid::new(0x01020304); let builder: UuidBuilder = uuid.into(); let builder: att::Uuid = uuid.into(); assert_eq!(builder.data[..12], BASE_UUID.to_le_bytes()[..12]); assert_eq!(builder.data[12..], [4, 3, 2, 1]); } Loading @@ -141,7 +130,7 @@ mod test { #[test] fn test_uuid_from_16_fixed_view() { let expected = Uuid::new(0x0102); let actual: Uuid = build_view_or_crash(Uuid16Builder { data: 0x0102 }).view().into(); let actual: Uuid = att::Uuid16 { data: 0x0102 }.try_into().unwrap(); assert_eq!(expected, actual); } Loading @@ -149,25 +138,21 @@ mod test { fn test_uuid_from_128_fixed_view() { let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let expected = Uuid::new_from_le_bytes(data); let actual: Uuid = build_view_or_crash(Uuid128Builder { data: data.into() }).view().into(); let actual: Uuid = att::Uuid128 { data }.try_into().unwrap(); assert_eq!(expected, actual); } #[test] fn test_uuid_from_16_view() { let expected = Uuid::new(0x0102); let actual: Uuid = build_view_or_crash(UuidBuilder { data: [2, 1].into() }).view().try_into().unwrap(); let actual: Uuid = att::Uuid { data: vec![2, 1] }.try_into().unwrap(); assert_eq!(expected, actual); } #[test] fn test_uuid_from_32_view() { let expected = Uuid::new(0x01020304); let actual: Uuid = build_view_or_crash(UuidBuilder { data: [4, 3, 2, 1].into() }) .view() .try_into() .unwrap(); let actual: Uuid = att::Uuid { data: vec![4, 3, 2, 1] }.try_into().unwrap(); assert_eq!(expected, actual); } Loading @@ -175,16 +160,14 @@ mod test { fn test_uuid_from_128_view() { let data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; let expected = Uuid::new_from_le_bytes(data); let actual: Uuid = build_view_or_crash(UuidBuilder { data: data.into() }).view().try_into().unwrap(); let actual: Uuid = att::Uuid { data: data.into() }.try_into().unwrap(); assert_eq!(expected, actual); } #[test] fn test_uuid_from_invalid_view() { let packet = build_view_or_crash(UuidBuilder { data: [10, 9, 8, 7, 6, 5, 4, 3, 2, 1].into() }); let res = Uuid::try_from(packet.view()); let packet = att::Uuid { data: vec![10, 9, 8, 7, 6, 5, 4, 3, 2, 1] }; let res = Uuid::try_from(packet); assert!(res.is_err()); } }
system/rust/src/gatt/arbiter.rs +23 −36 Original line number Diff line number Diff line //! This module handles "arbitration" of ATT packets, to determine whether they //! should be handled by the primary stack or by the Rust stack use pdl_runtime::Packet; use std::sync::{Arc, Mutex}; use log::{error, trace, warn}; use std::sync::RwLock; use crate::{ do_in_rust_thread, packets::{AttOpcode, OwnedAttView, OwnedPacket}, }; use crate::{do_in_rust_thread, packets::att}; use super::{ ffi::{InterceptAction, StoreCallbacksFromRust}, Loading Loading @@ -62,19 +60,19 @@ pub fn has_arbiter() -> bool { fn try_parse_att_server_packet( isolation_manager: &IsolationManager, tcb_idx: TransportIndex, packet: Box<[u8]>, ) -> Option<OwnedAttView> { packet: &[u8], ) -> Option<att::Att> { isolation_manager.get_server_id(tcb_idx)?; let att = OwnedAttView::try_parse(packet).ok()?; let att = att::Att::decode_full(packet).ok()?; if att.view().get_opcode() == AttOpcode::EXCHANGE_MTU_REQUEST { if att.opcode == att::AttOpcode::ExchangeMtuRequest { // special case: this server opcode is handled by legacy stack, and we snoop // on its handling, since the MTU is shared between the client + server return None; } match classify_opcode(att.view().get_opcode()) { match classify_opcode(att.opcode) { OperationType::Command | OperationType::Request | OperationType::Confirmation => Some(att), _ => None, } Loading Loading @@ -123,13 +121,13 @@ fn intercept_packet(tcb_idx: u8, packet: Vec<u8>) -> InterceptAction { } let tcb_idx = TransportIndex(tcb_idx); if let Some(att) = with_arbiter(|arbiter| { try_parse_att_server_packet(arbiter, tcb_idx, packet.into_boxed_slice()) }) { if let Some(att) = with_arbiter(|arbiter| try_parse_att_server_packet(arbiter, tcb_idx, &packet)) { do_in_rust_thread(move |modules| { trace!("pushing packet to GATT"); if let Some(bearer) = modules.gatt_module.get_bearer(tcb_idx) { bearer.handle_packet(att.view()) bearer.handle_packet(att) } else { error!("Bearer for {tcb_idx:?} not found"); } Loading Loading @@ -160,10 +158,7 @@ mod test { use crate::{ gatt::ids::{AttHandle, ServerId}, packets::{ AttBuilder, AttExchangeMtuRequestBuilder, AttOpcode, AttReadRequestBuilder, Serializable, }, packets::att, }; const TCB_IDX: TransportIndex = TransportIndex(1); Loading @@ -183,15 +178,12 @@ mod test { #[test] fn test_packet_capture_when_isolated() { let isolation_manager = create_manager_with_isolated_connection(TCB_IDX, SERVER_ID); let packet = AttBuilder { opcode: AttOpcode::READ_REQUEST, _child_: AttReadRequestBuilder { attribute_handle: AttHandle(1).into() }.into(), }; let packet = att::AttReadRequest { attribute_handle: AttHandle(1).into() }; let out = try_parse_att_server_packet( &isolation_manager, TCB_IDX, packet.to_vec().unwrap().into(), &packet.encode_to_vec().unwrap(), ); assert!(out.is_some()); Loading @@ -200,15 +192,16 @@ mod test { #[test] fn test_packet_bypass_when_isolated() { let isolation_manager = create_manager_with_isolated_connection(TCB_IDX, SERVER_ID); let packet = AttBuilder { opcode: AttOpcode::ERROR_RESPONSE, _child_: AttReadRequestBuilder { attribute_handle: AttHandle(1).into() }.into(), let packet = att::AttErrorResponse { opcode_in_error: att::AttOpcode::ReadResponse, handle_in_error: AttHandle(1).into(), error_code: att::AttErrorCode::InvalidHandle, }; let out = try_parse_att_server_packet( &isolation_manager, TCB_IDX, packet.to_vec().unwrap().into(), &packet.encode_to_vec().unwrap(), ); assert!(out.is_none()); Loading @@ -217,15 +210,12 @@ mod test { #[test] fn test_mtu_bypass() { let isolation_manager = create_manager_with_isolated_connection(TCB_IDX, SERVER_ID); let packet = AttBuilder { opcode: AttOpcode::EXCHANGE_MTU_REQUEST, _child_: AttExchangeMtuRequestBuilder { mtu: 64 }.into(), }; let packet = att::AttExchangeMtuRequest { mtu: 64 }; let out = try_parse_att_server_packet( &isolation_manager, TCB_IDX, packet.to_vec().unwrap().into(), &packet.encode_to_vec().unwrap(), ); assert!(out.is_none()); Loading @@ -234,15 +224,12 @@ mod test { #[test] fn test_packet_bypass_when_not_isolated() { let isolation_manager = IsolationManager::new(); let packet = AttBuilder { opcode: AttOpcode::READ_REQUEST, _child_: AttReadRequestBuilder { attribute_handle: AttHandle(1).into() }.into(), }; let packet = att::AttReadRequest { attribute_handle: AttHandle(1).into() }; let out = try_parse_att_server_packet( &isolation_manager, TCB_IDX, packet.to_vec().unwrap().into(), &packet.encode_to_vec().unwrap(), ); assert!(out.is_none()); Loading