diff --git a/examples/onoff_light/src/main.rs b/examples/onoff_light/src/main.rs index f3321921..1c3d25c2 100644 --- a/examples/onoff_light/src/main.rs +++ b/examples/onoff_light/src/main.rs @@ -15,7 +15,6 @@ * limitations under the License. */ -use core::borrow::Borrow; use core::pin::pin; use std::net::UdpSocket; @@ -108,7 +107,7 @@ fn run() -> Result<(), Error> { let mut mdns = pin!(run_mdns(&matter)); - let on_off = cluster_on_off::OnOffCluster::new(*matter.borrow()); + let on_off = cluster_on_off::OnOffCluster::new(Dataver::new_rand(matter.rand())); let subscriptions = Subscriptions::<3>::new(); @@ -153,7 +152,7 @@ fn run() -> Result<(), Error> { Some(( CommissioningData { // TODO: Hard-coded for now - verifier: VerifierData::new_with_pw(123456, *matter.borrow()), + verifier: VerifierData::new_with_pw(123456, matter.rand()), discriminator: 250, }, Default::default(), @@ -196,11 +195,11 @@ fn dm_handler<'a>( ) -> impl Metadata + NonBlockingHandler + 'a { ( NODE, - root_endpoint::eth_handler(0, matter) + root_endpoint::eth_handler(0, matter.rand()) .chain( 1, descriptor::ID, - descriptor::DescriptorCluster::new(*matter.borrow()), + descriptor::DescriptorCluster::new(Dataver::new_rand(matter.rand())), ) .chain(1, cluster_on_off::ID, on_off), ) diff --git a/rs-matter/src/core.rs b/rs-matter/src/core.rs index ae74af69..fd1d7e04 100644 --- a/rs-matter/src/core.rs +++ b/rs-matter/src/core.rs @@ -15,7 +15,7 @@ * limitations under the License. */ -use core::{borrow::Borrow, cell::RefCell}; +use core::cell::RefCell; use embassy_sync::blocking_mutex::raw::NoopRawMutex; @@ -27,7 +27,7 @@ use crate::{ }, error::*, fabric::FabricMgr, - mdns::{Mdns, MdnsService}, + mdns::MdnsService, pairing::{print_pairing_code_and_qr, DiscoveryCapabilities}, secure_channel::{pake::PaseMgr, spake2p::VerifierData}, transport::{ @@ -57,11 +57,11 @@ pub struct Matter<'a> { pub(crate) failsafe: RefCell, pub transport_mgr: TransportMgr<'a>, // Public for tests persist_notification: Notification, - pub(crate) epoch: Epoch, - pub(crate) rand: Rand, + epoch: Epoch, + rand: Rand, dev_det: &'a BasicInfoConfig<'a>, dev_att: &'a dyn DevAttDataFetcher, - pub(crate) port: u16, + port: u16, } impl<'a> Matter<'a> { @@ -125,6 +125,14 @@ impl<'a> Matter<'a> { self.port } + pub fn rand(&self) -> Rand { + self.rand + } + + pub fn epoch(&self) -> Epoch { + self.epoch + } + /// A utility method to replace the initial mDNS implementation with another one. /// /// Useful in particular with `MdnsService::Provided`, where the user would still like @@ -172,6 +180,21 @@ impl<'a> Matter<'a> { self.acl_mgr.borrow().is_changed() || self.fabric_mgr.borrow().is_changed() } + /// Return `true` if there is at least one commissioned fabric + // + // TODO: + // The implementation of this method needs to change in future, + // because the current implementation does not really track whether + // `CommissioningComplete` had been actually received for the fabric. + // + // The fabric is created once we receive `AddNoc`, but that's just + // not enough. The fabric should NOT be considered commissioned until + // after we receive `CommissioningComplete` on behalf of a Case session + // for the fabric in question. + pub fn is_commissioned(&self) -> bool { + self.fabric_mgr.borrow().used_count() > 0 + } + fn start_comissioning( &self, dev_comm: CommissioningData, @@ -261,63 +284,3 @@ impl<'a> Matter<'a> { self.persist_notification.wait().await } } - -impl<'a> Borrow> for Matter<'a> { - fn borrow(&self) -> &RefCell { - &self.fabric_mgr - } -} - -impl<'a> Borrow> for Matter<'a> { - fn borrow(&self) -> &RefCell { - &self.acl_mgr - } -} - -impl<'a> Borrow> for Matter<'a> { - fn borrow(&self) -> &RefCell { - &self.pase_mgr - } -} - -impl<'a> Borrow> for Matter<'a> { - fn borrow(&self) -> &RefCell { - &self.failsafe - } -} - -impl<'a> Borrow> for Matter<'a> { - fn borrow(&self) -> &TransportMgr<'a> { - &self.transport_mgr - } -} - -impl<'a> Borrow> for Matter<'a> { - fn borrow(&self) -> &BasicInfoConfig<'a> { - self.dev_det - } -} - -impl<'a> Borrow for Matter<'a> { - fn borrow(&self) -> &(dyn DevAttDataFetcher + 'a) { - self.dev_att - } -} - -impl<'a> Borrow for Matter<'a> { - fn borrow(&self) -> &(dyn Mdns + 'a) { - &self.transport_mgr.mdns - } -} - -impl<'a> Borrow for Matter<'a> { - fn borrow(&self) -> &Epoch { - &self.epoch - } -} - -impl<'a> Borrow for Matter<'a> { - fn borrow(&self) -> &Rand { - &self.rand - } -} diff --git a/rs-matter/src/data_model/cluster_basic_information.rs b/rs-matter/src/data_model/cluster_basic_information.rs index 8cc0915d..55b6a3ec 100644 --- a/rs-matter/src/data_model/cluster_basic_information.rs +++ b/rs-matter/src/data_model/cluster_basic_information.rs @@ -17,16 +17,16 @@ use core::cell::RefCell; -use super::objects::*; -use crate::{ - attribute_enum, - error::{Error, ErrorCode}, - utils::rand::Rand, -}; -use heapless::String; use rs_matter_macros::idl_import; + use strum::FromRepr; +use crate::attribute_enum; +use crate::error::{Error, ErrorCode}; +use crate::transport::exchange::Exchange; + +use super::objects::*; + idl_import!(clusters = ["BasicInformation"]); pub use basic_information::ID; @@ -136,40 +136,44 @@ pub const CLUSTER: Cluster<'static> = Cluster { }; #[derive(Clone)] -pub struct BasicInfoCluster<'a> { +pub struct BasicInfoCluster { data_ver: Dataver, - cfg: &'a BasicInfoConfig<'a>, - node_label: RefCell>, // Max node-label as per the spec + node_label: RefCell>, // Max node-label as per the spec } -impl<'a> BasicInfoCluster<'a> { - pub fn new(cfg: &'a BasicInfoConfig<'a>, rand: Rand) -> Self { - let node_label = RefCell::new("".try_into().unwrap()); +impl BasicInfoCluster { + pub const fn new(data_ver: Dataver) -> Self { Self { - data_ver: Dataver::new(rand), - cfg, - node_label, + data_ver, + node_label: RefCell::new(heapless::String::new()), } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) } else { + let cfg = exchange.matter().dev_det(); + match attr.attr_id.try_into()? { Attributes::DMRevision(codec) => codec.encode(writer, 1), - Attributes::VendorName(codec) => codec.encode(writer, self.cfg.vendor_name), - Attributes::VendorId(codec) => codec.encode(writer, self.cfg.vid), - Attributes::ProductName(codec) => codec.encode(writer, self.cfg.product_name), - Attributes::ProductId(codec) => codec.encode(writer, self.cfg.pid), + Attributes::VendorName(codec) => codec.encode(writer, cfg.vendor_name), + Attributes::VendorId(codec) => codec.encode(writer, cfg.vid), + Attributes::ProductName(codec) => codec.encode(writer, cfg.product_name), + Attributes::ProductId(codec) => codec.encode(writer, cfg.pid), Attributes::NodeLabel(codec) => { codec.encode(writer, self.node_label.borrow().as_str()) } - Attributes::HwVer(codec) => codec.encode(writer, self.cfg.hw_ver), - Attributes::SwVer(codec) => codec.encode(writer, self.cfg.sw_ver), - Attributes::SwVerString(codec) => codec.encode(writer, self.cfg.sw_ver_str), - Attributes::SerialNo(codec) => codec.encode(writer, self.cfg.serial_no), + Attributes::HwVer(codec) => codec.encode(writer, cfg.hw_ver), + Attributes::SwVer(codec) => codec.encode(writer, cfg.sw_ver), + Attributes::SwVerString(codec) => codec.encode(writer, cfg.sw_ver_str), + Attributes::SerialNo(codec) => codec.encode(writer, cfg.serial_no), } } } else { @@ -177,7 +181,12 @@ impl<'a> BasicInfoCluster<'a> { } } - pub fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + pub fn write( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + data: AttrData, + ) -> Result<(), Error> { let data = data.with_dataver(self.data_ver.get())?; match attr.attr_id.try_into()? { @@ -197,19 +206,24 @@ impl<'a> BasicInfoCluster<'a> { } } -impl<'a> Handler for BasicInfoCluster<'a> { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - BasicInfoCluster::read(self, attr, encoder) +impl Handler for BasicInfoCluster { + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + BasicInfoCluster::read(self, exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - BasicInfoCluster::write(self, attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + BasicInfoCluster::write(self, exchange, attr, data) } } -impl<'a> NonBlockingHandler for BasicInfoCluster<'a> {} +impl NonBlockingHandler for BasicInfoCluster {} -impl<'a> ChangeNotifier<()> for BasicInfoCluster<'a> { +impl ChangeNotifier<()> for BasicInfoCluster { fn consume_change(&mut self) -> Option<()> { self.data_ver.consume_change(()) } diff --git a/rs-matter/src/data_model/cluster_on_off.rs b/rs-matter/src/data_model/cluster_on_off.rs index 22372113..b6ea41f5 100644 --- a/rs-matter/src/data_model/cluster_on_off.rs +++ b/rs-matter/src/data_model/cluster_on_off.rs @@ -17,15 +17,19 @@ use core::cell::Cell; -use super::objects::*; -use crate::{ - attribute_enum, cmd_enter, command_enum, error::Error, tlv::TLVElement, - transport::exchange::Exchange, utils::rand::Rand, -}; use log::info; + use rs_matter_macros::idl_import; + use strum::{EnumDiscriminants, FromRepr}; +use crate::error::Error; +use crate::tlv::TLVElement; +use crate::transport::exchange::Exchange; +use crate::{attribute_enum, cmd_enter, command_enum}; + +use super::objects::*; + idl_import!(clusters = ["OnOff"]); pub use on_off::ID; @@ -68,9 +72,9 @@ pub struct OnOffCluster { } impl OnOffCluster { - pub fn new(rand: Rand) -> Self { + pub const fn new(data_ver: Dataver) -> Self { Self { - data_ver: Dataver::new(rand), + data_ver, on: Cell::new(false), } } @@ -86,7 +90,12 @@ impl OnOffCluster { } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -100,7 +109,12 @@ impl OnOffCluster { } } - pub fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + pub fn write( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + data: AttrData, + ) -> Result<(), Error> { let data = data.with_dataver(self.data_ver.get())?; match attr.attr_id.try_into()? { @@ -144,12 +158,17 @@ impl OnOffCluster { } impl Handler for OnOffCluster { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - OnOffCluster::read(self, attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + OnOffCluster::read(self, exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - OnOffCluster::write(self, attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + OnOffCluster::write(self, exchange, attr, data) } fn invoke( diff --git a/rs-matter/src/data_model/cluster_template.rs b/rs-matter/src/data_model/cluster_template.rs index 1e6adb8b..61b00226 100644 --- a/rs-matter/src/data_model/cluster_template.rs +++ b/rs-matter/src/data_model/cluster_template.rs @@ -15,11 +15,9 @@ * limitations under the License. */ -use crate::{ - data_model::objects::{Cluster, Handler}, - error::{Error, ErrorCode}, - utils::rand::Rand, -}; +use crate::data_model::objects::{Cluster, Handler}; +use crate::error::{Error, ErrorCode}; +use crate::transport::exchange::Exchange; use super::objects::{ AttrDataEncoder, AttrDetails, ChangeNotifier, Dataver, NonBlockingHandler, ATTRIBUTE_LIST, @@ -40,13 +38,16 @@ pub struct TemplateCluster { } impl TemplateCluster { - pub fn new(rand: Rand) -> Self { - Self { - data_ver: Dataver::new(rand), - } + pub const fn new(data_ver: Dataver) -> Self { + Self { data_ver } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -60,8 +61,13 @@ impl TemplateCluster { } impl Handler for TemplateCluster { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - TemplateCluster::read(self, attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + TemplateCluster::read(self, exchange, attr, encoder) } } diff --git a/rs-matter/src/data_model/core.rs b/rs-matter/src/data_model/core.rs index 49c96129..a3ebeb88 100644 --- a/rs-matter/src/data_model/core.rs +++ b/rs-matter/src/data_model/core.rs @@ -25,7 +25,6 @@ use embassy_futures::select::select3; use embassy_time::{Instant, Timer}; use log::{debug, error, info, warn}; -use crate::acl::Accessor; use crate::interaction_model::messages::ib::AttrStatus; use crate::utils::buf::BufferAccess; use crate::{error::*, Matter}; @@ -157,7 +156,7 @@ where // Will the clusters that are to be invoked await? let awaits = metadata.node().read(&req, None, &accessor).any(|item| { - item.map(|attr| self.handler.read_awaits(&attr)) + item.map(|attr| self.handler.read_awaits(exchange, &attr)) .unwrap_or(false) }); @@ -169,7 +168,7 @@ where let mut attrs = node.read(&req, None, &accessor).peekable(); if !req - .respond(&self.handler, None, &mut attrs, &mut wb, true) + .respond(&self.handler, exchange, None, &mut attrs, &mut wb, true) .await? { drop(attrs); @@ -210,7 +209,7 @@ where loop { let more_chunks = req - .respond(&self.handler, None, &mut attrs, &mut wb, true) + .respond(&self.handler, exchange, None, &mut attrs, &mut wb, true) .await?; exchange.send(OpCode::ReportData, wb.as_slice()).await?; @@ -256,7 +255,7 @@ where .node() .write(&req, &exchange.accessor()?) .any(|item| { - item.map(|(attr, _)| self.handler.write_awaits(&attr)) + item.map(|(attr, _)| self.handler.write_awaits(exchange, &attr)) .unwrap_or(false) }); @@ -272,24 +271,14 @@ where let req = WriteReq::from_tlv(&get_root_node_struct(&rx)?)?; - req.respond( - &self.handler, - &exchange.accessor()?, - &metadata.node(), - &mut wb, - ) - .await? + req.respond(&self.handler, exchange, &metadata.node(), &mut wb) + .await? } else { // No, they won't. Answer the request by directly using the RX packet // of the transport layer, as the operation won't await. - req.respond( - &self.handler, - &exchange.accessor()?, - &metadata.node(), - &mut wb, - ) - .await? + req.respond(&self.handler, exchange, &metadata.node(), &mut wb) + .await? }; exchange.send(OpCode::WriteResponse, wb.as_slice()).await?; @@ -326,7 +315,7 @@ where .node() .invoke(&req, &exchange.accessor()?) .any(|item| { - item.map(|(cmd, _)| self.handler.invoke_awaits(&cmd)) + item.map(|(cmd, _)| self.handler.invoke_awaits(exchange, &cmd)) .unwrap_or(false) }); @@ -561,7 +550,7 @@ where let req = TimedReq::from_tlv(&get_root_node_struct(exchange.rx()?.payload())?)?; debug!("IM: Timed request: {:?}", req); - let timeout_instant = req.timeout_instant(exchange.matter().epoch); + let timeout_instant = req.timeout_instant(exchange.matter().epoch()); Self::send_status(exchange, IMStatusCode::Success).await?; @@ -578,7 +567,7 @@ where if timed_req != timeout_instant.is_some() { Some(IMStatusCode::TimedRequestMisMatch) } else if timeout_instant - .map(|timeout_instant| (exchange.matter().epoch)() > timeout_instant) + .map(|timeout_instant| (exchange.matter().epoch())() > timeout_instant) .unwrap_or(false) { Some(IMStatusCode::Timeout) @@ -623,7 +612,14 @@ where loop { let more_chunks = req - .respond(&self.handler, Some(id), &mut attrs, &mut wb, false) + .respond( + &self.handler, + exchange, + Some(id), + &mut attrs, + &mut wb, + false, + ) .await?; exchange.send(OpCode::ReportData, wb.as_slice()).await?; @@ -742,6 +738,7 @@ impl<'a> ReportDataReq<'a> { pub(crate) async fn respond( &self, handler: T, + exchange: &Exchange<'_>, subscription_id: Option, attrs: &mut Peekable, wb: &mut WriteBuf<'_>, @@ -775,7 +772,7 @@ impl<'a> ReportDataReq<'a> { } while let Some(item) = attrs.peek() { - if AttrDataEncoder::handle_read(item, &handler, &mut tw).await? { + if AttrDataEncoder::handle_read(exchange, item, &handler, &mut tw).await? { attrs.next(); } else { break; @@ -809,13 +806,15 @@ impl<'a> WriteReq<'a> { async fn respond( &self, handler: T, - accessor: &Accessor<'_>, + exchange: &Exchange<'_>, node: &Node<'_>, wb: &mut WriteBuf<'_>, ) -> Result where T: DataModelHandler, { + let accessor = exchange.accessor()?; + wb.reset(); let mut tw = TLVWriter::new(wb); @@ -834,10 +833,10 @@ impl<'a> WriteReq<'a> { // Thus we support the Case1 by doing this. It does come at the cost of maintaining an // additional list of expanded write requests as we start processing those. let write_attrs: heapless::Vec<_, MAX_WRITE_ATTRS_IN_ONE_TRANS> = - node.write(self, accessor).collect(); + node.write(self, &accessor).collect(); for item in write_attrs { - AttrDataEncoder::handle_write(&item, &handler, &mut tw).await?; + AttrDataEncoder::handle_write(exchange, &item, &handler, &mut tw).await?; } tw.end_container()?; diff --git a/rs-matter/src/data_model/objects/dataver.rs b/rs-matter/src/data_model/objects/dataver.rs index 2c4c8175..47a766b1 100644 --- a/rs-matter/src/data_model/objects/dataver.rs +++ b/rs-matter/src/data_model/objects/dataver.rs @@ -16,32 +16,38 @@ */ use core::cell::Cell; +use core::num::Wrapping; use crate::utils::rand::Rand; -#[derive(Clone)] +#[derive(Debug, Clone, Eq, PartialEq)] pub struct Dataver { - ver: Cell, + ver: Cell>, changed: Cell, } impl Dataver { - pub fn new(rand: Rand) -> Self { - let mut buf = [0; 4]; - rand(&mut buf); + pub fn new_rand(rand: Rand) -> Self { + let mut bytes = [0; 4]; + rand(&mut bytes); + + Self::new(u32::from_le_bytes(bytes)) + } + + pub const fn new(initial: u32) -> Self { Self { - ver: Cell::new(u32::from_be_bytes(buf)), + ver: Cell::new(Wrapping(initial)), changed: Cell::new(false), } } pub fn get(&self) -> u32 { - self.ver.get() + self.ver.get().0 } pub fn changed(&self) -> u32 { - self.ver.set(self.ver.get().overflowing_add(1).0); + self.ver.set(self.ver.get() + Wrapping(1)); self.changed.set(true); self.get() diff --git a/rs-matter/src/data_model/objects/encoder.rs b/rs-matter/src/data_model/objects/encoder.rs index e24c1a00..ff5aaf86 100644 --- a/rs-matter/src/data_model/objects/encoder.rs +++ b/rs-matter/src/data_model/objects/encoder.rs @@ -125,6 +125,7 @@ pub struct AttrDataEncoder<'a, 'b, 'c> { impl<'a, 'b, 'c> AttrDataEncoder<'a, 'b, 'c> { pub async fn handle_read( + exchange: &Exchange<'_>, item: &Result, AttrStatus>, handler: &T, tw: &mut TLVWriter<'_, '_>, @@ -133,7 +134,7 @@ impl<'a, 'b, 'c> AttrDataEncoder<'a, 'b, 'c> { Ok(attr) => { let encoder = AttrDataEncoder::new(attr, tw); - let result = handler.read(attr, encoder).await; + let result = handler.read(exchange, attr, encoder).await; match result { Ok(()) => None, Err(e) => { @@ -156,13 +157,16 @@ impl<'a, 'b, 'c> AttrDataEncoder<'a, 'b, 'c> { } pub async fn handle_write( + exchange: &Exchange<'_>, item: &Result<(AttrDetails<'_>, TLVElement<'_>), AttrStatus>, handler: &T, tw: &mut TLVWriter<'_, '_>, ) -> Result<(), Error> { let status = match item { Ok((attr, data)) => { - let result = handler.write(attr, AttrData::new(attr.dataver, data)).await; + let result = handler + .write(exchange, attr, AttrData::new(attr.dataver, data)) + .await; match result { Ok(()) => attr.status(IMStatusCode::Success)?, Err(error) => attr.status(error.into())?, diff --git a/rs-matter/src/data_model/objects/handler.rs b/rs-matter/src/data_model/objects/handler.rs index 53a1d47b..65f4f9fa 100644 --- a/rs-matter/src/data_model/objects/handler.rs +++ b/rs-matter/src/data_model/objects/handler.rs @@ -37,9 +37,19 @@ pub trait ChangeNotifier { /// /// Prefer this trait when implementing handlers that are known to be non-blocking. pub trait Handler { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error>; + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error>; - fn write(&self, _attr: &AttrDetails, _data: AttrData) -> Result<(), Error> { + fn write( + &self, + _exchange: &Exchange, + _attr: &AttrDetails, + _data: AttrData, + ) -> Result<(), Error> { Err(ErrorCode::AttributeNotFound.into()) } @@ -58,12 +68,17 @@ impl Handler for &T where T: Handler, { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - (**self).read(attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + (**self).read(exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - (**self).write(attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + (**self).write(exchange, attr, data) } fn invoke( @@ -81,12 +96,17 @@ impl Handler for &mut T where T: Handler, { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - (**self).read(attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + (**self).read(exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - (**self).write(attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + (**self).write(exchange, attr, data) } fn invoke( @@ -111,12 +131,17 @@ impl Handler for (M, H) where H: Handler, { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - self.1.read(attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + self.1.read(exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - self.1.write(attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + self.1.write(exchange, attr, data) } fn invoke( @@ -161,7 +186,12 @@ impl EmptyHandler { } impl Handler for EmptyHandler { - fn read(&self, _attr: &AttrDetails, _encoder: AttrDataEncoder) -> Result<(), Error> { + fn read( + &self, + _exchange: &Exchange, + _attr: &AttrDetails, + _encoder: AttrDataEncoder, + ) -> Result<(), Error> { Err(ErrorCode::AttributeNotFound.into()) } } @@ -217,19 +247,24 @@ where H: Handler, T: Handler, { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if self.handler_endpoint == attr.endpoint_id && self.handler_cluster == attr.cluster_id { - self.handler.read(attr, encoder) + self.handler.read(exchange, attr, encoder) } else { - self.next.read(attr, encoder) + self.next.read(exchange, attr, encoder) } } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { if self.handler_endpoint == attr.endpoint_id && self.handler_cluster == attr.cluster_id { - self.handler.write(attr, data) + self.handler.write(exchange, attr, data) } else { - self.next.write(attr, data) + self.next.write(exchange, attr, data) } } @@ -279,12 +314,17 @@ impl Handler for HandlerCompat where T: Handler, { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - self.0.read(attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + self.0.read(exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - self.0.write(attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + self.0.write(exchange, attr, data) } fn invoke( @@ -365,7 +405,7 @@ mod asynch { /// /// The default implementation unconditionally returns `true` i.e. the handler is assumed to /// await while reading any attribute. - fn read_awaits(&self, _attr: &AttrDetails) -> bool { + fn read_awaits(&self, _exchange: &Exchange, _attr: &AttrDetails) -> bool { true } @@ -378,7 +418,7 @@ mod asynch { /// /// The default implementation unconditionally returns `true` i.e. the handler is assumed to /// await while writing any attribute. - fn write_awaits(&self, _attr: &AttrDetails) -> bool { + fn write_awaits(&self, _exchange: &Exchange, _attr: &AttrDetails) -> bool { true } @@ -391,24 +431,26 @@ mod asynch { /// /// The default implementation unconditionally returns `true` i.e. the handler is assumed to /// await while invoking any command. - fn invoke_awaits(&self, _cmd: &CmdDetails) -> bool { + fn invoke_awaits(&self, _exchange: &Exchange, _cmd: &CmdDetails) -> bool { true } /// Reads from the requested attribute and encodes the result using the provided encoder. - async fn read<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - encoder: AttrDataEncoder<'a, '_, '_>, + async fn read( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + encoder: AttrDataEncoder<'_, '_, '_>, ) -> Result<(), Error>; /// Writes into the requested attribute using the provided data. /// /// The default implementation errors out with `ErrorCode::AttributeNotFound`. - async fn write<'a>( - &'a self, - _attr: &'a AttrDetails<'_>, - _data: AttrData<'a>, + async fn write( + &self, + _exchange: &Exchange<'_>, + _attr: &AttrDetails<'_>, + _data: AttrData<'_>, ) -> Result<(), Error> { Err(ErrorCode::AttributeNotFound.into()) } @@ -416,12 +458,12 @@ mod asynch { /// Invokes the requested command with the provided data and encodes the result using the provided encoder. /// /// The default implementation errors out with `ErrorCode::CommandNotFound`. - async fn invoke<'a>( - &'a self, - _exchange: &'a Exchange<'_>, - _cmd: &'a CmdDetails<'_>, - _data: &'a TLVElement<'_>, - _encoder: CmdDataEncoder<'a, '_, '_>, + async fn invoke( + &self, + _exchange: &Exchange<'_>, + _cmd: &CmdDetails<'_>, + _data: &TLVElement<'_>, + _encoder: CmdDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { Err(ErrorCode::CommandNotFound.into()) } @@ -431,40 +473,42 @@ mod asynch { where T: AsyncHandler, { - fn read_awaits(&self, attr: &AttrDetails) -> bool { - (**self).read_awaits(attr) + fn read_awaits(&self, exchange: &Exchange, attr: &AttrDetails) -> bool { + (**self).read_awaits(exchange, attr) } - fn write_awaits(&self, attr: &AttrDetails) -> bool { - (**self).write_awaits(attr) + fn write_awaits(&self, exchange: &Exchange, attr: &AttrDetails) -> bool { + (**self).write_awaits(exchange, attr) } - fn invoke_awaits(&self, cmd: &CmdDetails) -> bool { - (**self).invoke_awaits(cmd) + fn invoke_awaits(&self, exchange: &Exchange, cmd: &CmdDetails) -> bool { + (**self).invoke_awaits(exchange, cmd) } - async fn read<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - encoder: AttrDataEncoder<'a, '_, '_>, + async fn read( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + encoder: AttrDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { - (**self).read(attr, encoder).await + (**self).read(exchange, attr, encoder).await } - async fn write<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - data: AttrData<'a>, + async fn write( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + data: AttrData<'_>, ) -> Result<(), Error> { - (**self).write(attr, data).await + (**self).write(exchange, attr, data).await } - async fn invoke<'a>( - &'a self, - exchange: &'a Exchange<'_>, - cmd: &'a CmdDetails<'_>, - data: &'a TLVElement<'_>, - encoder: CmdDataEncoder<'a, '_, '_>, + async fn invoke( + &self, + exchange: &Exchange<'_>, + cmd: &CmdDetails<'_>, + data: &TLVElement<'_>, + encoder: CmdDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { (**self).invoke(exchange, cmd, data, encoder).await } @@ -474,40 +518,42 @@ mod asynch { where T: AsyncHandler, { - fn read_awaits(&self, attr: &AttrDetails) -> bool { - (**self).read_awaits(attr) + fn read_awaits(&self, exchange: &Exchange, attr: &AttrDetails) -> bool { + (**self).read_awaits(exchange, attr) } - fn write_awaits(&self, attr: &AttrDetails) -> bool { - (**self).write_awaits(attr) + fn write_awaits(&self, exchange: &Exchange, attr: &AttrDetails) -> bool { + (**self).write_awaits(exchange, attr) } - fn invoke_awaits(&self, cmd: &CmdDetails) -> bool { - (**self).invoke_awaits(cmd) + fn invoke_awaits(&self, exchange: &Exchange, cmd: &CmdDetails) -> bool { + (**self).invoke_awaits(exchange, cmd) } - async fn read<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - encoder: AttrDataEncoder<'a, '_, '_>, + async fn read( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + encoder: AttrDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { - (**self).read(attr, encoder).await + (**self).read(exchange, attr, encoder).await } - async fn write<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - data: AttrData<'a>, + async fn write( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + data: AttrData<'_>, ) -> Result<(), Error> { - (**self).write(attr, data).await + (**self).write(exchange, attr, data).await } - async fn invoke<'a>( - &'a self, - exchange: &'a Exchange<'_>, - cmd: &'a CmdDetails<'_>, - data: &'a TLVElement<'_>, - encoder: CmdDataEncoder<'a, '_, '_>, + async fn invoke( + &self, + exchange: &Exchange<'_>, + cmd: &CmdDetails<'_>, + data: &TLVElement<'_>, + encoder: CmdDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { (**self).invoke(exchange, cmd, data, encoder).await } @@ -517,40 +563,42 @@ mod asynch { where H: AsyncHandler, { - fn read_awaits(&self, attr: &AttrDetails) -> bool { - self.1.read_awaits(attr) + fn read_awaits(&self, exchange: &Exchange, attr: &AttrDetails) -> bool { + self.1.read_awaits(exchange, attr) } - fn write_awaits(&self, attr: &AttrDetails) -> bool { - self.1.write_awaits(attr) + fn write_awaits(&self, exchange: &Exchange, attr: &AttrDetails) -> bool { + self.1.write_awaits(exchange, attr) } - fn invoke_awaits(&self, cmd: &CmdDetails) -> bool { - self.1.invoke_awaits(cmd) + fn invoke_awaits(&self, exchange: &Exchange, cmd: &CmdDetails) -> bool { + self.1.invoke_awaits(exchange, cmd) } - async fn read<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - encoder: AttrDataEncoder<'a, '_, '_>, + async fn read( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + encoder: AttrDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { - self.1.read(attr, encoder).await + self.1.read(exchange, attr, encoder).await } - async fn write<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - data: AttrData<'a>, + async fn write( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + data: AttrData<'_>, ) -> Result<(), Error> { - self.1.write(attr, data).await + self.1.write(exchange, attr, data).await } - async fn invoke<'a>( - &'a self, - exchange: &'a Exchange<'_>, - cmd: &'a CmdDetails<'_>, - data: &'a TLVElement<'_>, - encoder: CmdDataEncoder<'a, '_, '_>, + async fn invoke( + &self, + exchange: &Exchange<'_>, + cmd: &CmdDetails<'_>, + data: &TLVElement<'_>, + encoder: CmdDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { self.1.invoke(exchange, cmd, data, encoder).await } @@ -560,62 +608,65 @@ mod asynch { where T: NonBlockingHandler, { - fn read_awaits(&self, _attr: &AttrDetails) -> bool { + fn read_awaits(&self, _exchange: &Exchange, _attr: &AttrDetails) -> bool { false } - fn write_awaits(&self, _attr: &AttrDetails) -> bool { + fn write_awaits(&self, _exchange: &Exchange, _attr: &AttrDetails) -> bool { false } - fn invoke_awaits(&self, _cmd: &CmdDetails) -> bool { + fn invoke_awaits(&self, _exchange: &Exchange, _cmd: &CmdDetails) -> bool { false } - async fn read<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - encoder: AttrDataEncoder<'a, '_, '_>, + async fn read( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + encoder: AttrDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { - Handler::read(&self.0, attr, encoder) + Handler::read(&self.0, exchange, attr, encoder) } - async fn write<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - data: AttrData<'a>, + async fn write( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + data: AttrData<'_>, ) -> Result<(), Error> { - Handler::write(&self.0, attr, data) + Handler::write(&self.0, exchange, attr, data) } - async fn invoke<'a>( - &'a self, - exchange: &'a Exchange<'_>, - cmd: &'a CmdDetails<'_>, - data: &'a TLVElement<'_>, - encoder: CmdDataEncoder<'a, '_, '_>, + async fn invoke( + &self, + exchange: &Exchange<'_>, + cmd: &CmdDetails<'_>, + data: &TLVElement<'_>, + encoder: CmdDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { Handler::invoke(&self.0, exchange, cmd, data, encoder) } } impl AsyncHandler for EmptyHandler { - fn read_awaits(&self, _attr: &AttrDetails) -> bool { + fn read_awaits(&self, _exchange: &Exchange, _attr: &AttrDetails) -> bool { false } - fn write_awaits(&self, _attr: &AttrDetails) -> bool { + fn write_awaits(&self, _exchange: &Exchange, _attr: &AttrDetails) -> bool { false } - fn invoke_awaits(&self, _cmd: &CmdDetails) -> bool { + fn invoke_awaits(&self, _exchange: &Exchange, _cmd: &CmdDetails) -> bool { false } - async fn read<'a>( - &'a self, - _attr: &'a AttrDetails<'_>, - _encoder: AttrDataEncoder<'a, '_, '_>, + async fn read( + &self, + _exchange: &Exchange<'_>, + _attr: &AttrDetails<'_>, + _encoder: AttrDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { Err(ErrorCode::AttributeNotFound.into()) } @@ -626,64 +677,66 @@ mod asynch { H: AsyncHandler, T: AsyncHandler, { - fn read_awaits(&self, attr: &AttrDetails) -> bool { + fn read_awaits(&self, exchange: &Exchange, attr: &AttrDetails) -> bool { if self.handler_endpoint == attr.endpoint_id && self.handler_cluster == attr.cluster_id { - self.handler.read_awaits(attr) + self.handler.read_awaits(exchange, attr) } else { - self.next.read_awaits(attr) + self.next.read_awaits(exchange, attr) } } - fn write_awaits(&self, attr: &AttrDetails) -> bool { + fn write_awaits(&self, exchange: &Exchange, attr: &AttrDetails) -> bool { if self.handler_endpoint == attr.endpoint_id && self.handler_cluster == attr.cluster_id { - self.handler.write_awaits(attr) + self.handler.write_awaits(exchange, attr) } else { - self.next.write_awaits(attr) + self.next.write_awaits(exchange, attr) } } - fn invoke_awaits(&self, cmd: &CmdDetails) -> bool { + fn invoke_awaits(&self, exchange: &Exchange, cmd: &CmdDetails) -> bool { if self.handler_endpoint == cmd.endpoint_id && self.handler_cluster == cmd.cluster_id { - self.handler.invoke_awaits(cmd) + self.handler.invoke_awaits(exchange, cmd) } else { - self.next.invoke_awaits(cmd) + self.next.invoke_awaits(exchange, cmd) } } - async fn read<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - encoder: AttrDataEncoder<'a, '_, '_>, + async fn read( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + encoder: AttrDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { if self.handler_endpoint == attr.endpoint_id && self.handler_cluster == attr.cluster_id { - self.handler.read(attr, encoder).await + self.handler.read(exchange, attr, encoder).await } else { - self.next.read(attr, encoder).await + self.next.read(exchange, attr, encoder).await } } - async fn write<'a>( - &'a self, - attr: &'a AttrDetails<'_>, - data: AttrData<'a>, + async fn write( + &self, + exchange: &Exchange<'_>, + attr: &AttrDetails<'_>, + data: AttrData<'_>, ) -> Result<(), Error> { if self.handler_endpoint == attr.endpoint_id && self.handler_cluster == attr.cluster_id { - self.handler.write(attr, data).await + self.handler.write(exchange, attr, data).await } else { - self.next.write(attr, data).await + self.next.write(exchange, attr, data).await } } - async fn invoke<'a>( - &'a self, - exchange: &'a Exchange<'_>, - cmd: &'a CmdDetails<'_>, - data: &'a TLVElement<'_>, - encoder: CmdDataEncoder<'a, '_, '_>, + async fn invoke( + &self, + exchange: &Exchange<'_>, + cmd: &CmdDetails<'_>, + data: &TLVElement<'_>, + encoder: CmdDataEncoder<'_, '_, '_>, ) -> Result<(), Error> { if self.handler_endpoint == cmd.endpoint_id && self.handler_cluster == cmd.cluster_id { self.handler.invoke(exchange, cmd, data, encoder).await diff --git a/rs-matter/src/data_model/root_endpoint.rs b/rs-matter/src/data_model/root_endpoint.rs index f8297e38..ce86a603 100644 --- a/rs-matter/src/data_model/root_endpoint.rs +++ b/rs-matter/src/data_model/root_endpoint.rs @@ -1,35 +1,18 @@ -use core::{borrow::Borrow, cell::RefCell}; +use crate::handler_chain_type; +use crate::utils::rand::Rand; -use crate::{ - acl::AclMgr, - fabric::FabricMgr, - handler_chain_type, - mdns::Mdns, - secure_channel::pake::PaseMgr, - transport::core::TransportMgr, - utils::{epoch::Epoch, rand::Rand}, -}; - -use super::{ - cluster_basic_information::{self, BasicInfoCluster, BasicInfoConfig}, - objects::{Cluster, EmptyHandler, Endpoint, EndptId, HandlerCompat}, - sdm::{ - admin_commissioning::{self, AdminCommCluster}, - dev_att::DevAttDataFetcher, - ethernet_nw_diagnostics::{self, EthNwDiagCluster}, - failsafe::FailSafe, - general_commissioning::{self, GenCommCluster}, - general_diagnostics::{self, GenDiagCluster}, - group_key_management::{self, GrpKeyMgmtCluster}, - noc::{self, NocCluster}, - nw_commissioning::{self, EthNwCommCluster}, - wifi_nw_diagnostics, - }, - system_model::{ - access_control::{self, AccessControlCluster}, - descriptor::{self, DescriptorCluster}, - }, -}; +use super::cluster_basic_information::{self, BasicInfoCluster}; +use super::objects::{Cluster, Dataver, EmptyHandler, Endpoint, EndptId, HandlerCompat}; +use super::sdm::admin_commissioning::{self, AdminCommCluster}; +use super::sdm::ethernet_nw_diagnostics::{self, EthNwDiagCluster}; +use super::sdm::general_commissioning::{self, BasicCommissioningInfo, GenCommCluster}; +use super::sdm::general_diagnostics::{self, GenDiagCluster}; +use super::sdm::group_key_management::{self, GrpKeyMgmtCluster}; +use super::sdm::noc::{self, NocCluster}; +use super::sdm::nw_commissioning::{self, EthNwCommCluster}; +use super::sdm::wifi_nw_diagnostics; +use super::system_model::access_control::{self, AccessControlCluster}; +use super::system_model::descriptor::{self, DescriptorCluster}; const ETH_NW_CLUSTERS: [Cluster<'static>; 10] = [ descriptor::CLUSTER, @@ -91,159 +74,101 @@ pub type RootEndpointHandler<'a, NWCOMM, NWDIAG> = handler_chain_type!( NWCOMM, NWDIAG, HandlerCompat>, - HandlerCompat>, - HandlerCompat>, - HandlerCompat>, - HandlerCompat>, - HandlerCompat>, + HandlerCompat, + HandlerCompat, + HandlerCompat, + HandlerCompat, + HandlerCompat, HandlerCompat, HandlerCompat ); /// A utility function to instantiate the root (Endpoint 0) handler using Ethernet as the operational network. -pub fn eth_handler<'a, T>(endpoint_id: u16, matter: &'a T) -> EthRootEndpointHandler<'a> -where - T: Borrow> - + Borrow - + Borrow> - + Borrow> - + Borrow> - + Borrow> - + Borrow> - + Borrow - + Borrow - + Borrow - + 'a, -{ +pub fn eth_handler(endpoint_id: u16, rand: Rand) -> EthRootEndpointHandler<'static> { handler( endpoint_id, - matter, - EthNwCommCluster::new(*matter.borrow()), + EthNwCommCluster::new(Dataver::new_rand(rand)), ethernet_nw_diagnostics::ID, - EthNwDiagCluster::new(*matter.borrow()), + EthNwDiagCluster::new(Dataver::new_rand(rand)), true, + rand, ) } /// A utility function to instantiate the root (Endpoint 0) handler. -/// Besides a reference to the main `Matter` object, this function +/// Besides a `Rand` function, this function /// needs user-supplied implementations of the network commissioning /// and network diagnostics clusters. -// -// TODO: The borrow abstraction below is not of much use and only increases -// the size of the handlers, as they hold on to various managers instead -// of simply keeping a reference to the `Matter` object. Remove it in future. -pub fn handler<'a, NWCOMM, NWDIAG, T>( +pub fn handler( endpoint_id: u16, - matter: &'a T, nwcomm: NWCOMM, nwdiag_id: u32, nwdiag: NWDIAG, supports_concurrent_connection: bool, -) -> RootEndpointHandler<'a, NWCOMM, NWDIAG> -where - T: Borrow> - + Borrow - + Borrow> - + Borrow> - + Borrow> - + Borrow> - + Borrow> - + Borrow - + Borrow - + Borrow - + 'a, -{ + rand: Rand, +) -> RootEndpointHandler<'static, NWCOMM, NWDIAG> { wrap( endpoint_id, - matter.borrow(), - matter.borrow(), - matter.borrow(), - matter.borrow(), - matter.borrow(), - matter.borrow(), - matter.borrow(), - matter.borrow(), - *matter.borrow(), - *matter.borrow(), nwcomm, nwdiag_id, nwdiag, supports_concurrent_connection, + rand, ) } -#[allow(clippy::too_many_arguments)] -fn wrap<'a, NWCOMM, NWDIAG>( +fn wrap( endpoint_id: u16, - basic_info: &'a BasicInfoConfig<'a>, - dev_att: &'a dyn DevAttDataFetcher, - pase: &'a RefCell, - fabric: &'a RefCell, - acl: &'a RefCell, - failsafe: &'a RefCell, - transport_mgr: &'a TransportMgr<'a>, - mdns: &'a dyn Mdns, - epoch: Epoch, - rand: Rand, nwcomm: NWCOMM, nwdiag_id: u32, nwdiag: NWDIAG, supports_concurrent_connection: bool, -) -> RootEndpointHandler<'a, NWCOMM, NWDIAG> { + rand: Rand, +) -> RootEndpointHandler<'static, NWCOMM, NWDIAG> { EmptyHandler .chain( endpoint_id, group_key_management::ID, - HandlerCompat(GrpKeyMgmtCluster::new(rand)), + HandlerCompat(GrpKeyMgmtCluster::new(Dataver::new_rand(rand))), ) .chain( endpoint_id, general_diagnostics::ID, - HandlerCompat(GenDiagCluster::new(rand)), + HandlerCompat(GenDiagCluster::new(Dataver::new_rand(rand))), ) .chain( endpoint_id, access_control::ID, - HandlerCompat(AccessControlCluster::new(acl, rand)), + HandlerCompat(AccessControlCluster::new(Dataver::new_rand(rand))), ) .chain( endpoint_id, noc::ID, - HandlerCompat(NocCluster::new( - dev_att, - fabric, - acl, - failsafe, - transport_mgr, - mdns, - epoch, - rand, - )), + HandlerCompat(NocCluster::new(Dataver::new_rand(rand))), ) .chain( endpoint_id, admin_commissioning::ID, - HandlerCompat(AdminCommCluster::new(pase, mdns, rand)), + HandlerCompat(AdminCommCluster::new(Dataver::new_rand(rand))), ) .chain( endpoint_id, general_commissioning::ID, HandlerCompat(GenCommCluster::new( - failsafe, + Dataver::new_rand(rand), + BasicCommissioningInfo::new(), supports_concurrent_connection, - rand, )), ) .chain( endpoint_id, cluster_basic_information::ID, - HandlerCompat(BasicInfoCluster::new(basic_info, rand)), + HandlerCompat(BasicInfoCluster::new(Dataver::new_rand(rand))), ) .chain( endpoint_id, descriptor::ID, - HandlerCompat(DescriptorCluster::new(rand)), + HandlerCompat(DescriptorCluster::new(Dataver::new_rand(rand))), ) .chain(endpoint_id, nwdiag_id, nwdiag) .chain(endpoint_id, nw_commissioning::ID, nwcomm) diff --git a/rs-matter/src/data_model/sdm/admin_commissioning.rs b/rs-matter/src/data_model/sdm/admin_commissioning.rs index f0a41d07..d050fe22 100644 --- a/rs-matter/src/data_model/sdm/admin_commissioning.rs +++ b/rs-matter/src/data_model/sdm/admin_commissioning.rs @@ -15,20 +15,18 @@ * limitations under the License. */ -use core::cell::RefCell; +use log::info; + +use num_derive::FromPrimitive; + +use strum::{EnumDiscriminants, FromRepr}; use crate::data_model::objects::*; -use crate::mdns::Mdns; -use crate::secure_channel::pake::PaseMgr; use crate::secure_channel::spake2p::VerifierData; use crate::tlv::{FromTLV, Nullable, OctetStr, TLVElement}; use crate::transport::exchange::Exchange; -use crate::utils::rand::Rand; use crate::{attribute_enum, cmd_enter}; use crate::{command_enum, error::*}; -use log::info; -use num_derive::FromPrimitive; -use strum::{EnumDiscriminants, FromRepr}; pub const ID: u32 = 0x003C; @@ -98,23 +96,22 @@ pub struct OpenCommWindowReq<'a> { salt: OctetStr<'a>, } -#[derive(Clone)] -pub struct AdminCommCluster<'a> { +#[derive(Debug, Clone)] +pub struct AdminCommCluster { data_ver: Dataver, - pase_mgr: &'a RefCell, - mdns: &'a dyn Mdns, } -impl<'a> AdminCommCluster<'a> { - pub fn new(pase_mgr: &'a RefCell, mdns: &'a dyn Mdns, rand: Rand) -> Self { - Self { - data_ver: Dataver::new(rand), - pase_mgr, - mdns, - } +impl AdminCommCluster { + pub const fn new(data_ver: Dataver) -> Self { + Self { data_ver } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -134,13 +131,14 @@ impl<'a> AdminCommCluster<'a> { pub fn invoke( &self, + exchange: &Exchange, cmd: &CmdDetails, data: &TLVElement, _encoder: CmdDataEncoder, ) -> Result<(), Error> { match cmd.cmd_id.try_into()? { - Commands::OpenCommWindow => self.handle_command_opencomm_win(data)?, - Commands::RevokeComm => self.handle_command_revokecomm_win(data)?, + Commands::OpenCommWindow => self.handle_command_opencomm_win(exchange, data)?, + Commands::RevokeComm => self.handle_command_revokecomm_win(exchange, data)?, _ => Err(ErrorCode::CommandNotFound)?, } @@ -149,20 +147,38 @@ impl<'a> AdminCommCluster<'a> { Ok(()) } - fn handle_command_opencomm_win(&self, data: &TLVElement) -> Result<(), Error> { + fn handle_command_opencomm_win( + &self, + exchange: &Exchange, + data: &TLVElement, + ) -> Result<(), Error> { cmd_enter!("Open Commissioning Window"); let req = OpenCommWindowReq::from_tlv(data)?; let verifier = VerifierData::new(req.verifier.0, req.iterations, req.salt.0); - self.pase_mgr + exchange + .matter() + .pase_mgr .borrow_mut() - .enable_pase_session(verifier, req.discriminator, self.mdns)?; + .enable_pase_session( + verifier, + req.discriminator, + &exchange.matter().transport_mgr.mdns, + )?; Ok(()) } - fn handle_command_revokecomm_win(&self, _data: &TLVElement) -> Result<(), Error> { + fn handle_command_revokecomm_win( + &self, + exchange: &Exchange, + _data: &TLVElement, + ) -> Result<(), Error> { cmd_enter!("Revoke Commissioning Window"); - self.pase_mgr.borrow_mut().disable_pase_session(self.mdns)?; + exchange + .matter() + .pase_mgr + .borrow_mut() + .disable_pase_session(&exchange.matter().transport_mgr.mdns)?; // TODO: Send status code if no commissioning window is open @@ -170,25 +186,30 @@ impl<'a> AdminCommCluster<'a> { } } -impl<'a> Handler for AdminCommCluster<'a> { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - AdminCommCluster::read(self, attr, encoder) +impl Handler for AdminCommCluster { + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + AdminCommCluster::read(self, exchange, attr, encoder) } fn invoke( &self, - _exchange: &Exchange, + exchange: &Exchange, cmd: &CmdDetails, data: &TLVElement, encoder: CmdDataEncoder, ) -> Result<(), Error> { - AdminCommCluster::invoke(self, cmd, data, encoder) + AdminCommCluster::invoke(self, exchange, cmd, data, encoder) } } -impl<'a> NonBlockingHandler for AdminCommCluster<'a> {} +impl NonBlockingHandler for AdminCommCluster {} -impl<'a> ChangeNotifier<()> for AdminCommCluster<'a> { +impl ChangeNotifier<()> for AdminCommCluster { fn consume_change(&mut self) -> Option<()> { self.data_ver.consume_change(()) } diff --git a/rs-matter/src/data_model/sdm/ethernet_nw_diagnostics.rs b/rs-matter/src/data_model/sdm/ethernet_nw_diagnostics.rs index b9527411..dff849d5 100644 --- a/rs-matter/src/data_model/sdm/ethernet_nw_diagnostics.rs +++ b/rs-matter/src/data_model/sdm/ethernet_nw_diagnostics.rs @@ -14,14 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -use crate::{ - attribute_enum, cmd_enter, command_enum, data_model::objects::*, error::Error, tlv::TLVElement, - transport::exchange::Exchange, utils::rand::Rand, -}; + use log::info; + use rs_matter_macros::idl_import; + use strum::{EnumDiscriminants, FromRepr}; +use crate::data_model::objects::*; +use crate::error::Error; +use crate::tlv::TLVElement; +use crate::transport::exchange::Exchange; +use crate::{attribute_enum, cmd_enter, command_enum}; + idl_import!(clusters = ["EthernetNetworkDiagnostics"]); pub use ethernet_network_diagnostics::Commands; @@ -59,19 +64,22 @@ pub const CLUSTER: Cluster<'static> = Cluster { commands: &[CommandsDiscriminants::ResetCounts as _], }; -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct EthNwDiagCluster { data_ver: Dataver, } impl EthNwDiagCluster { - pub fn new(rand: Rand) -> Self { - Self { - data_ver: Dataver::new(rand), - } + pub const fn new(data_ver: Dataver) -> Self { + Self { data_ver } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -86,7 +94,12 @@ impl EthNwDiagCluster { } } - pub fn write(&self, _attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + pub fn write( + &self, + _exchange: &Exchange, + _attr: &AttrDetails, + data: AttrData, + ) -> Result<(), Error> { let _data = data.with_dataver(self.data_ver.get())?; self.data_ver.changed(); @@ -114,12 +127,17 @@ impl EthNwDiagCluster { } impl Handler for EthNwDiagCluster { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - EthNwDiagCluster::read(self, attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + EthNwDiagCluster::read(self, exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - EthNwDiagCluster::write(self, attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + EthNwDiagCluster::write(self, exchange, attr, data) } fn invoke( diff --git a/rs-matter/src/data_model/sdm/general_commissioning.rs b/rs-matter/src/data_model/sdm/general_commissioning.rs index 5d185b35..8340dd2d 100644 --- a/rs-matter/src/data_model/sdm/general_commissioning.rs +++ b/rs-matter/src/data_model/sdm/general_commissioning.rs @@ -15,19 +15,18 @@ * limitations under the License. */ -use core::cell::RefCell; +use log::info; + +use rs_matter_macros::idl_import; + +use strum::{EnumDiscriminants, FromRepr}; use crate::data_model::objects::*; -use crate::data_model::sdm::failsafe::FailSafe; use crate::tlv::{FromTLV, TLVElement, ToTLV, UtfStr}; use crate::transport::exchange::Exchange; use crate::transport::session::SessionMode; -use crate::utils::rand::Rand; use crate::{attribute_enum, cmd_enter}; use crate::{command_enum, error::*}; -use log::info; -use rs_matter_macros::idl_import; -use strum::{EnumDiscriminants, FromRepr}; idl_import!(clusters = ["GeneralCommissioning"]); @@ -109,43 +108,54 @@ struct FailSafeParams { bread_crumb: u64, } -#[derive(ToTLV, Clone)] -struct BasicCommissioningInfo { - expiry_len: u16, - max_cmltv_failsafe_secs: u16, +#[derive(FromTLV, ToTLV, Debug, Clone)] +pub struct BasicCommissioningInfo { + pub expiry_len: u16, + pub max_cmltv_failsafe_secs: u16, } -#[derive(Clone)] -pub struct GenCommCluster<'a> { +impl BasicCommissioningInfo { + pub const fn new() -> Self { + // TODO: Arch-Specific + Self { + expiry_len: 120, + max_cmltv_failsafe_secs: 120, + } + } +} + +impl Default for BasicCommissioningInfo { + fn default() -> Self { + BasicCommissioningInfo::new() + } +} + +#[derive(Debug, Clone)] +pub struct GenCommCluster { data_ver: Dataver, basic_comm_info: BasicCommissioningInfo, supports_concurrent_connection: bool, - failsafe: &'a RefCell, } -impl<'a> GenCommCluster<'a> { - pub fn new( - failsafe: &'a RefCell, +impl GenCommCluster { + pub const fn new( + data_ver: Dataver, + basic_comm_info: BasicCommissioningInfo, supports_concurrent_connection: bool, - rand: Rand, ) -> Self { Self { - data_ver: Dataver::new(rand), - failsafe, - // TODO: Arch-Specific - basic_comm_info: BasicCommissioningInfo { - expiry_len: 120, - max_cmltv_failsafe_secs: 120, - }, + data_ver, + basic_comm_info, supports_concurrent_connection, } } - pub fn failsafe(&self) -> &RefCell { - self.failsafe - } - - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(mut writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -207,7 +217,8 @@ impl<'a> GenCommCluster<'a> { let p = FailSafeParams::from_tlv(data)?; - let status = if self + let status = if exchange + .matter() .failsafe .borrow_mut() .arm( @@ -276,7 +287,8 @@ impl<'a> GenCommCluster<'a> { // AddNOC or UpdateNOC must have happened, and that too for the same fabric // scope that is for this session - if self + if exchange + .matter() .failsafe .borrow_mut() .disarm(exchange.with_session(|sess| Ok(sess.get_session_mode().clone()))?) @@ -298,9 +310,14 @@ impl<'a> GenCommCluster<'a> { } } -impl<'a> Handler for GenCommCluster<'a> { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - GenCommCluster::read(self, attr, encoder) +impl Handler for GenCommCluster { + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + GenCommCluster::read(self, exchange, attr, encoder) } fn invoke( @@ -314,9 +331,9 @@ impl<'a> Handler for GenCommCluster<'a> { } } -impl<'a> NonBlockingHandler for GenCommCluster<'a> {} +impl NonBlockingHandler for GenCommCluster {} -impl<'a> ChangeNotifier<()> for GenCommCluster<'a> { +impl ChangeNotifier<()> for GenCommCluster { fn consume_change(&mut self) -> Option<()> { self.data_ver.consume_change(()) } diff --git a/rs-matter/src/data_model/sdm/general_diagnostics.rs b/rs-matter/src/data_model/sdm/general_diagnostics.rs index c4fce155..7b2d2934 100644 --- a/rs-matter/src/data_model/sdm/general_diagnostics.rs +++ b/rs-matter/src/data_model/sdm/general_diagnostics.rs @@ -14,17 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -use crate::{ - attribute_enum, cmd_enter, command_enum, - data_model::objects::*, - error::{Error, ErrorCode}, - tlv::TLVElement, - transport::exchange::Exchange, - utils::rand::Rand, -}; + use log::info; + use strum::{EnumDiscriminants, FromRepr}; +use crate::data_model::objects::*; +use crate::error::{Error, ErrorCode}; +use crate::tlv::TLVElement; +use crate::transport::exchange::Exchange; +use crate::{attribute_enum, cmd_enter, command_enum}; + pub const ID: u32 = 0x0033; #[derive(FromRepr, EnumDiscriminants)] @@ -70,19 +70,22 @@ pub const CLUSTER: Cluster<'static> = Cluster { commands: &[CommandsDiscriminants::TestEventTrigger as _], }; -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct GenDiagCluster { data_ver: Dataver, } impl GenDiagCluster { - pub fn new(rand: Rand) -> Self { - Self { - data_ver: Dataver::new(rand), - } + pub const fn new(data_ver: Dataver) -> Self { + Self { data_ver } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -97,7 +100,12 @@ impl GenDiagCluster { } } - pub fn write(&self, _attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + pub fn write( + &self, + _exchange: &Exchange, + _attr: &AttrDetails, + data: AttrData, + ) -> Result<(), Error> { let _data = data.with_dataver(self.data_ver.get())?; self.data_ver.changed(); @@ -125,12 +133,17 @@ impl GenDiagCluster { } impl Handler for GenDiagCluster { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - GenDiagCluster::read(self, attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + GenDiagCluster::read(self, exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - GenDiagCluster::write(self, attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + GenDiagCluster::write(self, exchange, attr, data) } fn invoke( diff --git a/rs-matter/src/data_model/sdm/group_key_management.rs b/rs-matter/src/data_model/sdm/group_key_management.rs index c597da61..e751e78d 100644 --- a/rs-matter/src/data_model/sdm/group_key_management.rs +++ b/rs-matter/src/data_model/sdm/group_key_management.rs @@ -14,17 +14,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -use crate::{ - attribute_enum, cmd_enter, command_enum, - data_model::objects::*, - error::{Error, ErrorCode}, - tlv::TLVElement, - transport::exchange::Exchange, - utils::rand::Rand, -}; + use log::info; + use strum::{EnumDiscriminants, FromRepr}; +use crate::data_model::objects::*; +use crate::error::{Error, ErrorCode}; +use crate::tlv::TLVElement; +use crate::transport::exchange::Exchange; +use crate::{attribute_enum, cmd_enter, command_enum}; + pub const ID: u32 = 0x003F; #[derive(FromRepr, EnumDiscriminants)] @@ -76,19 +76,22 @@ pub const CLUSTER: Cluster<'static> = Cluster { commands: &[CommandsDiscriminants::KeySetWrite as _], }; -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct GrpKeyMgmtCluster { data_ver: Dataver, } impl GrpKeyMgmtCluster { - pub fn new(rand: Rand) -> Self { - Self { - data_ver: Dataver::new(rand), - } + pub const fn new(data_ver: Dataver) -> Self { + Self { data_ver } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -104,7 +107,12 @@ impl GrpKeyMgmtCluster { } } - pub fn write(&self, _attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + pub fn write( + &self, + _exchange: &Exchange, + _attr: &AttrDetails, + data: AttrData, + ) -> Result<(), Error> { let _data = data.with_dataver(self.data_ver.get())?; self.data_ver.changed(); @@ -132,12 +140,17 @@ impl GrpKeyMgmtCluster { } impl Handler for GrpKeyMgmtCluster { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - GrpKeyMgmtCluster::read(self, attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + GrpKeyMgmtCluster::read(self, exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - GrpKeyMgmtCluster::write(self, attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + GrpKeyMgmtCluster::write(self, exchange, attr, data) } fn invoke( diff --git a/rs-matter/src/data_model/sdm/noc.rs b/rs-matter/src/data_model/sdm/noc.rs index e59b1eea..64e44f30 100644 --- a/rs-matter/src/data_model/sdm/noc.rs +++ b/rs-matter/src/data_model/sdm/noc.rs @@ -15,29 +15,27 @@ * limitations under the License. */ -use core::cell::{Cell, RefCell}; +use core::cell::Cell; use core::num::NonZeroU8; -use crate::acl::{AclEntry, AclMgr, AuthMode}; +use log::{error, info, warn}; + +use strum::{EnumDiscriminants, FromRepr}; + +use crate::acl::{AclEntry, AuthMode}; use crate::cert::{Cert, MAX_CERT_TLV_LEN}; use crate::crypto::{self, KeyPair}; use crate::data_model::objects::*; use crate::data_model::sdm::dev_att; -use crate::fabric::{Fabric, FabricMgr, MAX_SUPPORTED_FABRICS}; -use crate::mdns::Mdns; +use crate::fabric::{Fabric, MAX_SUPPORTED_FABRICS}; use crate::tlv::{FromTLV, OctetStr, TLVElement, TLVWriter, TagType, ToTLV, UtfStr}; -use crate::transport::core::TransportMgr; use crate::transport::exchange::Exchange; use crate::transport::session::SessionMode; use crate::utils::epoch::Epoch; -use crate::utils::rand::Rand; use crate::utils::writebuf::WriteBuf; use crate::{attribute_enum, cmd_enter, command_enum, error::*}; -use log::{error, info, warn}; -use strum::{EnumDiscriminants, FromRepr}; use super::dev_att::{DataType, DevAttDataFetcher}; -use super::failsafe::FailSafe; // Node Operational Credentials Cluster @@ -215,45 +213,22 @@ struct RemoveFabricReq { fab_idx: NonZeroU8, } -#[derive(Clone)] -pub struct NocCluster<'a> { +#[derive(Debug, Clone)] +pub struct NocCluster { data_ver: Dataver, - epoch: Epoch, - rand: Rand, - dev_att: &'a dyn DevAttDataFetcher, - fabric_mgr: &'a RefCell, - acl_mgr: &'a RefCell, - failsafe: &'a RefCell, - transport_mgr: &'a TransportMgr<'a>, - mdns: &'a dyn Mdns, } -impl<'a> NocCluster<'a> { - #[allow(clippy::too_many_arguments)] - pub fn new( - dev_att: &'a dyn DevAttDataFetcher, - fabric_mgr: &'a RefCell, - acl_mgr: &'a RefCell, - failsafe: &'a RefCell, - transport_mgr: &'a TransportMgr<'a>, - mdns: &'a dyn Mdns, - epoch: Epoch, - rand: Rand, - ) -> Self { - Self { - data_ver: Dataver::new(rand), - epoch, - rand, - dev_att, - fabric_mgr, - acl_mgr, - failsafe, - transport_mgr, - mdns, - } +impl NocCluster { + pub const fn new(data_ver: Dataver) -> Self { + Self { data_ver } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(mut writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -265,24 +240,29 @@ impl<'a> NocCluster<'a> { Attributes::CurrentFabricIndex(codec) => codec.encode(writer, attr.fab_idx), Attributes::Fabrics(_) => { writer.start_array(AttrDataWriter::TAG)?; - self.fabric_mgr.borrow().for_each(|entry, fab_idx| { - if !attr.fab_filter || attr.fab_idx == fab_idx.get() { - let root_ca_cert = entry.get_root_ca()?; - - entry - .get_fabric_desc(fab_idx, &root_ca_cert)? - .to_tlv(&mut writer, TagType::Anonymous)?; - } - - Ok(()) - })?; + exchange + .matter() + .fabric_mgr + .borrow() + .for_each(|entry, fab_idx| { + if !attr.fab_filter || attr.fab_idx == fab_idx.get() { + let root_ca_cert = entry.get_root_ca()?; + + entry + .get_fabric_desc(fab_idx, &root_ca_cert)? + .to_tlv(&mut writer, TagType::Anonymous)?; + } + + Ok(()) + })?; writer.end_container()?; writer.complete() } - Attributes::CommissionedFabrics(codec) => { - codec.encode(writer, self.fabric_mgr.borrow().used_count() as _) - } + Attributes::CommissionedFabrics(codec) => codec.encode( + writer, + exchange.matter().fabric_mgr.borrow().used_count() as _, + ), _ => { error!("Attribute not supported: this shouldn't happen"); Err(ErrorCode::AttributeNotFound.into()) @@ -331,7 +311,8 @@ impl<'a> NocCluster<'a> { .with_session(|sess| Ok(sess.take_noc_data()))? .ok_or(NocStatus::MissingCsr)?; - if !self + if !exchange + .matter() .failsafe .borrow_mut() .allow_noc_change() @@ -374,10 +355,11 @@ impl<'a> NocCluster<'a> { ) .map_err(|_| NocStatus::TableFull)?; - let fab_idx = self + let fab_idx = exchange + .matter() .fabric_mgr .borrow_mut() - .add(fabric, self.mdns) + .add(fabric, &exchange.matter().transport_mgr.mdns) .map_err(|_| NocStatus::TableFull)?; let succeeded = Cell::new(false); @@ -387,16 +369,18 @@ impl<'a> NocCluster<'a> { // Remove the fabric if we fail further down this function warn!("Removing fabric {} due to failure", fab_idx.get()); - self.fabric_mgr + exchange + .matter() + .fabric_mgr .borrow_mut() - .remove(fab_idx, self.mdns) + .remove(fab_idx, &exchange.matter().transport_mgr.mdns) .unwrap(); } }); let mut acl = AclEntry::new(fab_idx, Privilege::ADMIN, AuthMode::Case); acl.add_subject(r.case_admin_subject)?; - let acl_entry_index = self.acl_mgr.borrow_mut().add(acl)?; + let acl_entry_index = exchange.matter().acl_mgr.borrow_mut().add(acl)?; let _acl_guard = scopeguard::guard(fab_idx, |fab_idx| { if !succeeded.get() { @@ -407,14 +391,20 @@ impl<'a> NocCluster<'a> { fab_idx.get() ); - self.acl_mgr + exchange + .matter() + .acl_mgr .borrow_mut() .delete(acl_entry_index, fab_idx) .unwrap(); } }); - self.failsafe.borrow_mut().record_add_noc(fab_idx)?; + exchange + .matter() + .failsafe + .borrow_mut() + .record_add_noc(fab_idx)?; // Finally, upgrade our session with the new fabric index exchange.with_session(|sess| { @@ -459,7 +449,8 @@ impl<'a> NocCluster<'a> { let (result, fab_idx) = if let SessionMode::Case { fab_idx, .. } = exchange.with_session(|sess| Ok(sess.get_session_mode().clone()))? { - if self + if exchange + .matter() .fabric_mgr .borrow_mut() .set_label( @@ -484,24 +475,31 @@ impl<'a> NocCluster<'a> { fn handle_command_rmfabric( &self, - _exchange: &Exchange, + exchange: &Exchange, data: &TLVElement, encoder: CmdDataEncoder, ) -> Result<(), Error> { cmd_enter!("Remove Fabric"); let req = RemoveFabricReq::from_tlv(data).map_err(Error::map_invalid_data_type)?; - if self + if exchange + .matter() .fabric_mgr .borrow_mut() - .remove(req.fab_idx, self.mdns) + .remove(req.fab_idx, &exchange.matter().transport_mgr.mdns) .is_ok() { - let _ = self.acl_mgr.borrow_mut().delete_for_fabric(req.fab_idx); - self.transport_mgr + let _ = exchange + .matter() + .acl_mgr + .borrow_mut() + .delete_for_fabric(req.fab_idx); + exchange + .matter() + .transport_mgr .session_mgr .borrow_mut() .remove_for_fabric(req.fab_idx); - self.transport_mgr.session_removed.notify(); + exchange.matter().transport_mgr.session_removed.notify(); // Note that since we might have removed our own session, the exchange // will terminate with a "NoSession" error, but that's OK and handled properly @@ -559,14 +557,14 @@ impl<'a> NocCluster<'a> { let mut attest_element = WriteBuf::new(&mut buf); writer.start_struct(CmdDataWriter::TAG)?; add_attestation_element( - self.epoch, - self.dev_att, + exchange.matter().epoch(), + exchange.matter().dev_att(), req.str.0, &mut attest_element, &mut writer, )?; add_attestation_signature( - self.dev_att, + exchange.matter().dev_att(), &mut attest_element, &attest_challenge, &mut writer, @@ -580,7 +578,7 @@ impl<'a> NocCluster<'a> { fn handle_command_certchainrequest( &self, - _exchange: &Exchange, + exchange: &Exchange, data: &TLVElement, encoder: CmdDataEncoder, ) -> Result<(), Error> { @@ -590,7 +588,10 @@ impl<'a> NocCluster<'a> { let cert_type = get_certchainrequest_params(data).map_err(Error::map_invalid_command)?; let mut buf: [u8; RESP_MAX] = [0; RESP_MAX]; - let len = self.dev_att.get_devatt_data(cert_type, &mut buf)?; + let len = exchange + .matter() + .dev_att() + .get_devatt_data(cert_type, &mut buf)?; let buf = &buf[0..len]; let cmd_data = CertChainResp { @@ -615,11 +616,11 @@ impl<'a> NocCluster<'a> { let req = CommonReq::from_tlv(data).map_err(Error::map_invalid_command)?; info!("Received CSR Nonce:{:?}", req.str); - if !self.failsafe.borrow().is_armed() { + if !exchange.matter().failsafe.borrow().is_armed() { Err(ErrorCode::UnsupportedAccess)?; } - let noc_keypair = KeyPair::new(self.rand)?; + let noc_keypair = KeyPair::new(exchange.matter().rand())?; let mut attest_challenge = [0u8; crypto::SYMM_KEY_LEN_BYTES]; exchange.with_session(|sess| { attest_challenge.copy_from_slice(sess.get_att_challenge()); @@ -633,7 +634,7 @@ impl<'a> NocCluster<'a> { writer.start_struct(CmdDataWriter::TAG)?; add_nocsrelement(&noc_keypair, req.str.0, &mut nocsr_element, &mut writer)?; add_attestation_signature( - self.dev_att, + exchange.matter().dev_att(), &mut nocsr_element, &attest_challenge, &mut writer, @@ -673,7 +674,7 @@ impl<'a> NocCluster<'a> { data: &TLVElement, ) -> Result<(), Error> { cmd_enter!("AddTrustedRootCert"); - if !self.failsafe.borrow().is_armed() { + if !exchange.matter().failsafe.borrow().is_armed() { Err(ErrorCode::UnsupportedAccess)?; } @@ -693,9 +694,14 @@ impl<'a> NocCluster<'a> { } } -impl<'a> Handler for NocCluster<'a> { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - NocCluster::read(self, attr, encoder) +impl Handler for NocCluster { + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + NocCluster::read(self, exchange, attr, encoder) } fn invoke( @@ -709,9 +715,9 @@ impl<'a> Handler for NocCluster<'a> { } } -impl<'a> NonBlockingHandler for NocCluster<'a> {} +impl NonBlockingHandler for NocCluster {} -impl<'a> ChangeNotifier<()> for NocCluster<'a> { +impl ChangeNotifier<()> for NocCluster { fn consume_change(&mut self) -> Option<()> { self.data_ver.consume_change(()) } diff --git a/rs-matter/src/data_model/sdm/nw_commissioning.rs b/rs-matter/src/data_model/sdm/nw_commissioning.rs index db9b8a3f..50501ef2 100644 --- a/rs-matter/src/data_model/sdm/nw_commissioning.rs +++ b/rs-matter/src/data_model/sdm/nw_commissioning.rs @@ -16,18 +16,17 @@ */ use rs_matter_macros::FromTLV; + use strum::FromRepr; -use crate::{ - attribute_enum, command_enum, - data_model::objects::{ - Access, AttrDataEncoder, AttrDataWriter, AttrDetails, AttrType, Attribute, ChangeNotifier, - Cluster, Dataver, Handler, NonBlockingHandler, Quality, ATTRIBUTE_LIST, FEATURE_MAP, - }, - error::{Error, ErrorCode}, - tlv::{OctetStr, TLVArray, TagType, ToTLV}, - utils::rand::Rand, +use crate::data_model::objects::{ + Access, AttrDataEncoder, AttrDataWriter, AttrDetails, AttrType, Attribute, ChangeNotifier, + Cluster, Dataver, Handler, NonBlockingHandler, Quality, ATTRIBUTE_LIST, FEATURE_MAP, }; +use crate::error::{Error, ErrorCode}; +use crate::tlv::{OctetStr, TLVArray, TagType, ToTLV}; +use crate::transport::exchange::Exchange; +use crate::{attribute_enum, command_enum}; pub const ID: u32 = 0x0031; @@ -270,15 +269,59 @@ pub struct ThreadInterfaceScanResult<'a> { pub lqi: u8, } -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct EthNwCommCluster { data_ver: Dataver, } impl EthNwCommCluster { - pub fn new(rand: Rand) -> Self { - Self { - data_ver: Dataver::new(rand), + pub const fn new(data_ver: Dataver) -> Self { + Self { data_ver } + } + + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + let info = self.get_network_info(); + if let Some(mut writer) = encoder.with_dataver(self.data_ver.get())? { + if attr.is_system() { + ETH_CLUSTER.read(attr.attr_id, writer) + } else { + match attr.attr_id.try_into()? { + Attributes::MaxNetworks => AttrType::::new().encode(writer, 1), + Attributes::Networks => { + writer.start_array(AttrDataWriter::TAG)?; + info.nw_info.to_tlv(&mut writer, TagType::Anonymous)?; + writer.end_container()?; + writer.complete() + } + Attributes::ConnectMaxTimeSecs => { + AttrType::::new().encode(writer, info.connect_max_time_secs) + } + Attributes::InterfaceEnabled => { + AttrType::::new().encode(writer, info.interface_enabled) + } + Attributes::LastNetworkingStatus => { + AttrType::::new().encode(writer, info.last_nw_status as u8) + } + Attributes::LastNetworkID => { + info.nw_info + .network_id + .to_tlv(&mut writer, AttrDataWriter::TAG)?; + writer.complete() + } + Attributes::LastConnectErrorValue => { + writer.null(AttrDataWriter::TAG)?; + writer.complete() + } + _ => Err(ErrorCode::AttributeNotFound.into()), + } + } + } else { + Ok(()) } } @@ -330,45 +373,13 @@ pub enum NetworkCommissioningStatus { } impl Handler for EthNwCommCluster { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - let info = self.get_network_info(); - if let Some(mut writer) = encoder.with_dataver(self.data_ver.get())? { - if attr.is_system() { - ETH_CLUSTER.read(attr.attr_id, writer) - } else { - match attr.attr_id.try_into()? { - Attributes::MaxNetworks => AttrType::::new().encode(writer, 1), - Attributes::Networks => { - writer.start_array(AttrDataWriter::TAG)?; - info.nw_info.to_tlv(&mut writer, TagType::Anonymous)?; - writer.end_container()?; - writer.complete() - } - Attributes::ConnectMaxTimeSecs => { - AttrType::::new().encode(writer, info.connect_max_time_secs) - } - Attributes::InterfaceEnabled => { - AttrType::::new().encode(writer, info.interface_enabled) - } - Attributes::LastNetworkingStatus => { - AttrType::::new().encode(writer, info.last_nw_status as u8) - } - Attributes::LastNetworkID => { - info.nw_info - .network_id - .to_tlv(&mut writer, AttrDataWriter::TAG)?; - writer.complete() - } - Attributes::LastConnectErrorValue => { - writer.null(AttrDataWriter::TAG)?; - writer.complete() - } - _ => Err(ErrorCode::AttributeNotFound.into()), - } - } - } else { - Ok(()) - } + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + EthNwCommCluster::read(self, exchange, attr, encoder) } } diff --git a/rs-matter/src/data_model/sdm/wifi_nw_diagnostics.rs b/rs-matter/src/data_model/sdm/wifi_nw_diagnostics.rs index 6eb5784b..868009b3 100644 --- a/rs-matter/src/data_model/sdm/wifi_nw_diagnostics.rs +++ b/rs-matter/src/data_model/sdm/wifi_nw_diagnostics.rs @@ -17,20 +17,18 @@ use core::cell::RefCell; -use crate::{ - attribute_enum, command_enum, - data_model::objects::*, - error::{Error, ErrorCode}, - tlv::{TLVElement, TagType}, - transport::exchange::Exchange, - utils::rand::Rand, -}; - use log::info; use rs_matter_macros::{FromTLV, ToTLV}; + use strum::{EnumDiscriminants, FromRepr}; +use crate::data_model::objects::*; +use crate::error::{Error, ErrorCode}; +use crate::tlv::{TLVElement, TagType}; +use crate::transport::exchange::Exchange; +use crate::{attribute_enum, command_enum}; + pub const ID: u32 = 0x0036; #[derive(FromRepr, EnumDiscriminants)] @@ -144,7 +142,7 @@ pub struct WifiNwDiagData { } /// A cluster implementing the Matter Wifi Diagnostics Cluster. -#[derive(Clone)] +#[derive(Debug, Clone)] pub struct WifiNwDiagCluster { data_ver: Dataver, data: RefCell, @@ -152,9 +150,9 @@ pub struct WifiNwDiagCluster { impl WifiNwDiagCluster { /// Create a new instance. - pub fn new(rand: Rand, data: WifiNwDiagData) -> Self { + pub const fn new(data_ver: Dataver, data: WifiNwDiagData) -> Self { Self { - data_ver: Dataver::new(rand), + data_ver, data: RefCell::new(data), } } @@ -171,7 +169,12 @@ impl WifiNwDiagCluster { } /// Read the value of an attribute. - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(mut writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -193,7 +196,12 @@ impl WifiNwDiagCluster { } /// Write the value of an attribute. - pub fn write(&self, _attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + pub fn write( + &self, + _exchange: &Exchange, + _attr: &AttrDetails, + data: AttrData, + ) -> Result<(), Error> { let _data = data.with_dataver(self.data_ver.get())?; self.data_ver.changed(); @@ -222,12 +230,17 @@ impl WifiNwDiagCluster { } impl Handler for WifiNwDiagCluster { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - WifiNwDiagCluster::read(self, attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + WifiNwDiagCluster::read(self, exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - WifiNwDiagCluster::write(self, attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + WifiNwDiagCluster::write(self, exchange, attr, data) } fn invoke( diff --git a/rs-matter/src/data_model/system_model/access_control.rs b/rs-matter/src/data_model/system_model/access_control.rs index aedf3a80..aa7daeb0 100644 --- a/rs-matter/src/data_model/system_model/access_control.rs +++ b/rs-matter/src/data_model/system_model/access_control.rs @@ -15,18 +15,18 @@ * limitations under the License. */ -use core::cell::RefCell; use core::num::NonZeroU8; use strum::{EnumDiscriminants, FromRepr}; +use log::{error, info}; + use crate::acl::{self, AclEntry, AclMgr}; use crate::data_model::objects::*; use crate::interaction_model::messages::ib::{attr_list_write, ListOperation}; use crate::tlv::{FromTLV, TLVElement, TagType, ToTLV}; -use crate::utils::rand::Rand; +use crate::transport::exchange::Exchange; use crate::{attribute_enum, error::*}; -use log::{error, info}; pub const ID: u32 = 0x001F; @@ -77,21 +77,55 @@ pub const CLUSTER: Cluster<'static> = Cluster { commands: &[], }; -#[derive(Clone)] -pub struct AccessControlCluster<'a> { +#[derive(Debug, Clone)] +pub struct AccessControlCluster { data_ver: Dataver, - acl_mgr: &'a RefCell, } -impl<'a> AccessControlCluster<'a> { - pub fn new(acl_mgr: &'a RefCell, rand: Rand) -> Self { - Self { - data_ver: Dataver::new(rand), - acl_mgr, +impl AccessControlCluster { + pub const fn new(data_ver: Dataver) -> Self { + Self { data_ver } + } + + pub fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + self.read_acl_attr(&exchange.matter().acl_mgr.borrow(), attr, encoder) + } + + pub fn write( + &self, + exchange: &Exchange, + attr: &AttrDetails, + data: AttrData, + ) -> Result<(), Error> { + match attr.attr_id.try_into()? { + Attributes::Acl(_) => { + attr_list_write(attr, data.with_dataver(self.data_ver.get())?, |op, data| { + self.write_acl_attr( + &mut exchange.matter().acl_mgr.borrow_mut(), + &op, + data, + NonZeroU8::new(attr.fab_idx).ok_or(ErrorCode::Invalid)?, + ) + }) + } + _ => { + error!("Attribute not yet supported: this shouldn't happen"); + Err(ErrorCode::AttributeNotFound.into()) + } } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + fn read_acl_attr( + &self, + acl_mgr: &AclMgr, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(mut writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -99,7 +133,7 @@ impl<'a> AccessControlCluster<'a> { match attr.attr_id.try_into()? { Attributes::Acl(_) => { writer.start_array(AttrDataWriter::TAG)?; - self.acl_mgr.borrow().for_each_acl(|entry| { + acl_mgr.for_each_acl(|entry| { if !attr.fab_filter || attr.fab_idx == entry.fab_idx.get() { entry.to_tlv(&mut writer, TagType::Anonymous)?; } @@ -133,30 +167,13 @@ impl<'a> AccessControlCluster<'a> { } } - pub fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - match attr.attr_id.try_into()? { - Attributes::Acl(_) => { - attr_list_write(attr, data.with_dataver(self.data_ver.get())?, |op, data| { - self.write_acl_attr( - &op, - data, - NonZeroU8::new(attr.fab_idx).ok_or(ErrorCode::Invalid)?, - ) - }) - } - _ => { - error!("Attribute not yet supported: this shouldn't happen"); - Err(ErrorCode::AttributeNotFound.into()) - } - } - } - /// Write the ACL Attribute /// /// This takes care of 4 things, add item, edit item, delete item, delete list. /// Care about fabric-scoped behaviour is taken fn write_acl_attr( &self, + acl_mgr: &mut AclMgr, op: &ListOperation, data: &TLVElement, fab_idx: NonZeroU8, @@ -170,36 +187,37 @@ impl<'a> AccessControlCluster<'a> { acl_entry.fab_idx = fab_idx; if let ListOperation::EditItem(index) = op { - self.acl_mgr - .borrow_mut() - .edit(*index as u8, fab_idx, acl_entry)?; + acl_mgr.edit(*index as u8, fab_idx, acl_entry)?; } else { - self.acl_mgr.borrow_mut().add(acl_entry)?; + acl_mgr.add(acl_entry)?; } Ok(()) } - ListOperation::DeleteItem(index) => { - self.acl_mgr.borrow_mut().delete(*index as u8, fab_idx) - } - ListOperation::DeleteList => self.acl_mgr.borrow_mut().delete_for_fabric(fab_idx), + ListOperation::DeleteItem(index) => acl_mgr.delete(*index as u8, fab_idx), + ListOperation::DeleteList => acl_mgr.delete_for_fabric(fab_idx), } } } -impl<'a> Handler for AccessControlCluster<'a> { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - AccessControlCluster::read(self, attr, encoder) +impl Handler for AccessControlCluster { + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + AccessControlCluster::read(self, exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - AccessControlCluster::write(self, attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + AccessControlCluster::write(self, exchange, attr, data) } } -impl<'a> NonBlockingHandler for AccessControlCluster<'a> {} +impl NonBlockingHandler for AccessControlCluster {} -impl<'a> ChangeNotifier<()> for AccessControlCluster<'a> { +impl ChangeNotifier<()> for AccessControlCluster { fn consume_change(&mut self) -> Option<()> { self.data_ver.consume_change(()) } @@ -207,15 +225,12 @@ impl<'a> ChangeNotifier<()> for AccessControlCluster<'a> { #[cfg(test)] mod tests { - use core::cell::RefCell; - - use crate::{ - acl::{AclEntry, AclMgr, AuthMode}, - data_model::objects::{AttrDataEncoder, AttrDetails, Node, Privilege}, - interaction_model::messages::ib::ListOperation, - tlv::{get_root_node_struct, ElementType, TLVElement, TLVWriter, TagType, ToTLV}, - utils::{rand::dummy_rand, writebuf::WriteBuf}, - }; + use crate::acl::{AclEntry, AclMgr, AuthMode}; + use crate::data_model::objects::{AttrDataEncoder, AttrDetails, Node, Privilege}; + use crate::data_model::system_model::access_control::Dataver; + use crate::interaction_model::messages::ib::ListOperation; + use crate::tlv::{get_root_node_struct, ElementType, TLVElement, TLVWriter, TagType, ToTLV}; + use crate::utils::writebuf::WriteBuf; use super::AccessControlCluster; @@ -228,8 +243,8 @@ mod tests { let mut writebuf = WriteBuf::new(&mut buf); let mut tw = TLVWriter::new(&mut writebuf); - let acl_mgr = RefCell::new(AclMgr::new()); - let acl = AccessControlCluster::new(&acl_mgr, dummy_rand); + let mut acl_mgr = AclMgr::new(); + let acl = AccessControlCluster::new(Dataver::new(0)); let new = AclEntry::new(FAB_2, Privilege::VIEW, AuthMode::Case); new.to_tlv(&mut tw, TagType::Anonymous).unwrap(); @@ -237,12 +252,11 @@ mod tests { // Test, ACL has fabric index 2, but the accessing fabric is 1 // the fabric index in the TLV should be ignored and the ACL should be created with entry 1 - let result = acl.write_acl_attr(&ListOperation::AddItem, &data, FAB_1); + let result = acl.write_acl_attr(&mut acl_mgr, &ListOperation::AddItem, &data, FAB_1); assert!(result.is_ok()); let verifier = AclEntry::new(FAB_1, Privilege::VIEW, AuthMode::Case); acl_mgr - .borrow() .for_each_acl(|a| { assert_eq!(*a, verifier); Ok(()) @@ -258,23 +272,23 @@ mod tests { let mut tw = TLVWriter::new(&mut writebuf); // Add 3 ACLs, belonging to fabric index 2, 1 and 2, in that order - let acl_mgr = RefCell::new(AclMgr::new()); + let mut acl_mgr = AclMgr::new(); let mut verifier = [ AclEntry::new(FAB_2, Privilege::VIEW, AuthMode::Case), AclEntry::new(FAB_1, Privilege::VIEW, AuthMode::Case), AclEntry::new(FAB_2, Privilege::ADMIN, AuthMode::Case), ]; for i in &verifier { - acl_mgr.borrow_mut().add(i.clone()).unwrap(); + acl_mgr.add(i.clone()).unwrap(); } - let acl = AccessControlCluster::new(&acl_mgr, dummy_rand); + let acl = AccessControlCluster::new(Dataver::new(0)); let new = AclEntry::new(FAB_2, Privilege::VIEW, AuthMode::Case); new.to_tlv(&mut tw, TagType::Anonymous).unwrap(); let data = get_root_node_struct(writebuf.as_slice()).unwrap(); // Test, Edit Fabric 2's index 1 - with accessing fabring as 2 - allow - let result = acl.write_acl_attr(&ListOperation::EditItem(1), &data, FAB_2); + let result = acl.write_acl_attr(&mut acl_mgr, &ListOperation::EditItem(1), &data, FAB_2); // Fabric 2's index 1, is actually our index 2, update the verifier verifier[2] = new; assert!(result.is_ok()); @@ -282,7 +296,6 @@ mod tests { // Also validate in the acl_mgr that the entries are in the right order let mut index = 0; acl_mgr - .borrow() .for_each_acl(|a| { assert_eq!(*a, verifier[index]); index += 1; @@ -295,28 +308,27 @@ mod tests { /// - The listindex used for delete should be relative to the current fabric fn acl_cluster_delete() { // Add 3 ACLs, belonging to fabric index 2, 1 and 2, in that order - let acl_mgr = RefCell::new(AclMgr::new()); + let mut acl_mgr = AclMgr::new(); let input = [ AclEntry::new(FAB_2, Privilege::VIEW, AuthMode::Case), AclEntry::new(FAB_1, Privilege::VIEW, AuthMode::Case), AclEntry::new(FAB_2, Privilege::ADMIN, AuthMode::Case), ]; for i in &input { - acl_mgr.borrow_mut().add(i.clone()).unwrap(); + acl_mgr.add(i.clone()).unwrap(); } - let acl = AccessControlCluster::new(&acl_mgr, dummy_rand); + let acl = AccessControlCluster::new(Dataver::new(0)); // data is don't-care actually let data = TLVElement::new(TagType::Anonymous, ElementType::True); // Test , Delete Fabric 1's index 0 - let result = acl.write_acl_attr(&ListOperation::DeleteItem(0), &data, FAB_1); + let result = acl.write_acl_attr(&mut acl_mgr, &ListOperation::DeleteItem(0), &data, FAB_1); assert!(result.is_ok()); let verifier = [input[0].clone(), input[2].clone()]; // Also validate in the acl_mgr that the entries are in the right order let mut index = 0; acl_mgr - .borrow() .for_each_acl(|a| { assert_eq!(*a, verifier[index]); index += 1; @@ -332,16 +344,16 @@ mod tests { let mut writebuf = WriteBuf::new(&mut buf); // Add 3 ACLs, belonging to fabric index 2, 1 and 2, in that order - let acl_mgr = RefCell::new(AclMgr::new()); + let mut acl_mgr = AclMgr::new(); let input = [ AclEntry::new(FAB_2, Privilege::VIEW, AuthMode::Case), AclEntry::new(FAB_1, Privilege::VIEW, AuthMode::Case), AclEntry::new(FAB_2, Privilege::ADMIN, AuthMode::Case), ]; for i in input { - acl_mgr.borrow_mut().add(i).unwrap(); + acl_mgr.add(i).unwrap(); } - let acl = AccessControlCluster::new(&acl_mgr, dummy_rand); + let acl = AccessControlCluster::new(Dataver::new(0)); // Test 1, all 3 entries are read in the response without fabric filtering { let attr = AttrDetails { @@ -362,7 +374,7 @@ mod tests { let mut tw = TLVWriter::new(&mut writebuf); let encoder = AttrDataEncoder::new(&attr, &mut tw); - acl.read(&attr, encoder).unwrap(); + acl.read_acl_attr(&acl_mgr, &attr, encoder).unwrap(); assert_eq!( // &[ // 21, 53, 1, 36, 0, 0, 55, 1, 24, 54, 2, 21, 36, 1, 1, 36, 2, 2, 54, 3, 24, 54, @@ -401,7 +413,7 @@ mod tests { let mut tw = TLVWriter::new(&mut writebuf); let encoder = AttrDataEncoder::new(&attr, &mut tw); - acl.read(&attr, encoder).unwrap(); + acl.read_acl_attr(&acl_mgr, &attr, encoder).unwrap(); assert_eq!( // &[ // 21, 53, 1, 36, 0, 0, 55, 1, 24, 54, 2, 21, 36, 1, 1, 36, 2, 2, 54, 3, 24, 54, @@ -436,7 +448,7 @@ mod tests { let mut tw = TLVWriter::new(&mut writebuf); let encoder = AttrDataEncoder::new(&attr, &mut tw); - acl.read(&attr, encoder).unwrap(); + acl.read_acl_attr(&acl_mgr, &attr, encoder).unwrap(); assert_eq!( // &[ // 21, 53, 1, 36, 0, 0, 55, 1, 24, 54, 2, 21, 36, 1, 1, 36, 2, 2, 54, 3, 24, 54, diff --git a/rs-matter/src/data_model/system_model/descriptor.rs b/rs-matter/src/data_model/system_model/descriptor.rs index 4d5bdbb5..21d29572 100644 --- a/rs-matter/src/data_model/system_model/descriptor.rs +++ b/rs-matter/src/data_model/system_model/descriptor.rs @@ -15,13 +15,15 @@ * limitations under the License. */ +use core::fmt::Debug; + use strum::FromRepr; use crate::attribute_enum; use crate::data_model::objects::*; use crate::error::Error; use crate::tlv::{TLVWriter, TagType, ToTLV}; -use crate::utils::rand::Rand; +use crate::transport::exchange::Exchange; pub const ID: u32 = 0x001D; @@ -51,6 +53,7 @@ pub const CLUSTER: Cluster<'static> = Cluster { commands: &[], }; +#[derive(Debug)] struct StandardPartsMatcher; impl PartsMatcher for StandardPartsMatcher { @@ -59,6 +62,7 @@ impl PartsMatcher for StandardPartsMatcher { } } +#[derive(Debug)] struct AggregatorPartsMatcher; impl PartsMatcher for AggregatorPartsMatcher { @@ -67,7 +71,7 @@ impl PartsMatcher for AggregatorPartsMatcher { } } -pub trait PartsMatcher { +pub trait PartsMatcher: Debug { fn describe(&self, our_endpoint: EndptId, endpoint: EndptId) -> bool; } @@ -91,29 +95,34 @@ where #[derive(Clone)] pub struct DescriptorCluster<'a> { - matcher: &'a dyn PartsMatcher, data_ver: Dataver, + matcher: &'a dyn PartsMatcher, } impl DescriptorCluster<'static> { - pub fn new(rand: Rand) -> Self { - Self::new_matching(&StandardPartsMatcher, rand) + pub const fn new(data_ver: Dataver) -> Self { + Self::new_matching(data_ver, &StandardPartsMatcher) } - pub fn new_aggregator(rand: Rand) -> Self { - Self::new_matching(&AggregatorPartsMatcher, rand) + pub const fn new_aggregator(data_ver: Dataver) -> Self { + Self::new_matching(data_ver, &AggregatorPartsMatcher) } } impl<'a> DescriptorCluster<'a> { - pub fn new_matching(matcher: &'a dyn PartsMatcher, rand: Rand) -> DescriptorCluster<'a> { - Self { - matcher, - data_ver: Dataver::new(rand), - } + pub const fn new_matching( + data_ver: Dataver, + matcher: &'a dyn PartsMatcher, + ) -> DescriptorCluster<'a> { + Self { data_ver, matcher } } - pub fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + pub fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { if let Some(mut writer) = encoder.with_dataver(self.data_ver.get())? { if attr.is_system() { CLUSTER.read(attr.attr_id, writer) @@ -231,8 +240,13 @@ impl<'a> DescriptorCluster<'a> { } impl<'a> Handler for DescriptorCluster<'a> { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - DescriptorCluster::read(self, attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + DescriptorCluster::read(self, exchange, attr, encoder) } } diff --git a/rs-matter/src/secure_channel/case.rs b/rs-matter/src/secure_channel/case.rs index 3052cadb..1ecfd6cd 100644 --- a/rs-matter/src/secure_channel/case.rs +++ b/rs-matter/src/secure_channel/case.rs @@ -253,7 +253,7 @@ impl Case { ); // Create an ephemeral Key Pair - let key_pair = KeyPair::new(exchange.matter().rand)?; + let key_pair = KeyPair::new(exchange.matter().rand())?; let _ = key_pair.get_public_key(&mut case_session.our_pub_key)?; // Derive the Shared Secret @@ -265,7 +265,7 @@ impl Case { // println!("Derived secret: {:x?} len: {}", secret, len); let mut our_random: [u8; 32] = [0; 32]; - (exchange.matter().rand)(&mut our_random); + (exchange.matter().rand())(&mut our_random); // Derive the Encrypted Part const MAX_ENCRYPTED_SIZE: usize = 800; @@ -301,7 +301,7 @@ impl Case { let encrypted_len = Case::get_sigma2_encryption( fabric, - exchange.matter().rand, + exchange.matter().rand(), &our_random, case_session, signature, diff --git a/rs-matter/src/transport/exchange.rs b/rs-matter/src/transport/exchange.rs index eeb4e5b0..4d800251 100644 --- a/rs-matter/src/transport/exchange.rs +++ b/rs-matter/src/transport/exchange.rs @@ -593,7 +593,7 @@ impl<'a> TxMessage<'a> { let (peer, retransmission) = session.pre_send( Some(self.exchange_id.exchange_index()), &mut self.packet.header, - self.matter.epoch, + self.matter.epoch(), )?; self.packet.peer = peer; @@ -839,7 +839,7 @@ impl<'a> Exchange<'a> { received_timeout_ms: u32, ) -> Result { if received_timeout_ms > 0 { - let epoch = matter.epoch; + let epoch = matter.epoch(); loop { let mut accept = pin!(matter.transport_mgr.accept_if(matter, |_, exch, _| { diff --git a/rs-matter/tests/common/echo_cluster.rs b/rs-matter/tests/common/echo_cluster.rs index afd2dae8..43117133 100644 --- a/rs-matter/tests/common/echo_cluster.rs +++ b/rs-matter/tests/common/echo_cluster.rs @@ -30,7 +30,6 @@ use rs_matter::{ interaction_model::messages::ib::{attr_list_write, ListOperation}, tlv::{TLVElement, TagType}, transport::exchange::Exchange, - utils::rand::Rand, }; use strum::{EnumDiscriminants, FromRepr}; @@ -135,9 +134,9 @@ pub struct EchoCluster { } impl EchoCluster { - pub fn new(multiplier: u8, rand: Rand) -> Self { + pub const fn new(multiplier: u8, data_ver: Dataver) -> Self { Self { - data_ver: Dataver::new(rand), + data_ver, multiplier, att1: Cell::new(0x1234), att2: Cell::new(0x5678), @@ -264,11 +263,16 @@ pub const ATTR_CUSTOM_VALUE: u32 = 0xcafebeef; pub const ATTR_WRITE_DEFAULT_VALUE: u16 = 0xcafe; impl Handler for EchoCluster { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { + fn read( + &self, + _exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { EchoCluster::read(self, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + fn write(&self, _exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { EchoCluster::write(self, attr, data) } diff --git a/rs-matter/tests/common/im_engine.rs b/rs-matter/tests/common/im_engine.rs index bee9e19f..3a0b3b5d 100644 --- a/rs-matter/tests/common/im_engine.rs +++ b/rs-matter/tests/common/im_engine.rs @@ -15,10 +15,10 @@ * limitations under the License. */ -use crate::common::echo_cluster; -use core::borrow::Borrow; use core::num::NonZeroU8; +use crate::common::echo_cluster; + use embassy_futures::{block_on, join::join, select::select3}; use embassy_sync::{ @@ -36,8 +36,8 @@ use rs_matter::{ core::{DataModel, IMBuffer}, device_types::{DEV_TYPE_ON_OFF_LIGHT, DEV_TYPE_ROOT_NODE}, objects::{ - AttrData, AttrDataEncoder, AttrDetails, Endpoint, Handler, HandlerCompat, Metadata, - Node, NonBlockingHandler, Privilege, + AttrData, AttrDataEncoder, AttrDetails, Dataver, Endpoint, Handler, HandlerCompat, + Metadata, Node, NonBlockingHandler, Privilege, }, root_endpoint::{self, EthRootEndpointHandler}, sdm::{ @@ -154,11 +154,27 @@ pub struct ImEngineHandler<'a> { impl<'a> ImEngineHandler<'a> { pub fn new(matter: &'a Matter<'a>) -> Self { - let handler = root_endpoint::eth_handler(0, matter) - .chain(0, echo_cluster::ID, EchoCluster::new(2, *matter.borrow())) - .chain(1, descriptor::ID, DescriptorCluster::new(*matter.borrow())) - .chain(1, echo_cluster::ID, EchoCluster::new(3, *matter.borrow())) - .chain(1, cluster_on_off::ID, OnOffCluster::new(*matter.borrow())); + let handler = root_endpoint::eth_handler(0, matter.rand()) + .chain( + 0, + echo_cluster::ID, + EchoCluster::new(2, Dataver::new_rand(matter.rand())), + ) + .chain( + 1, + descriptor::ID, + DescriptorCluster::new(Dataver::new_rand(matter.rand())), + ) + .chain( + 1, + echo_cluster::ID, + EchoCluster::new(3, Dataver::new_rand(matter.rand())), + ) + .chain( + 1, + cluster_on_off::ID, + OnOffCluster::new(Dataver::new_rand(matter.rand())), + ); Self { handler } } @@ -173,12 +189,17 @@ impl<'a> ImEngineHandler<'a> { } impl<'a> Handler for ImEngineHandler<'a> { - fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error> { - self.handler.read(attr, encoder) + fn read( + &self, + exchange: &Exchange, + attr: &AttrDetails, + encoder: AttrDataEncoder, + ) -> Result<(), Error> { + self.handler.read(exchange, attr, encoder) } - fn write(&self, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { - self.handler.write(attr, data) + fn write(&self, exchange: &Exchange, attr: &AttrDetails, data: AttrData) -> Result<(), Error> { + self.handler.write(exchange, attr, data) } fn invoke(