From eb21772a095c53a2916cdb7e7b1c335f4e33afc1 Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Fri, 9 Jun 2023 07:47:49 +0000 Subject: [PATCH] Simplify main user-facing API --- examples/onoff_light/src/main.rs | 29 ++++--- matter/src/core.rs | 53 +++++++++--- matter/src/data_model/root_endpoint.rs | 8 +- matter/src/secure_channel/core.rs | 30 +++++-- matter/src/secure_channel/pake.rs | 4 + matter/src/transport/{mgr.rs => core.rs} | 102 +++++++++++------------ matter/src/transport/exchange.rs | 1 + matter/src/transport/mod.rs | 2 +- matter/tests/common/im_engine.rs | 6 +- 9 files changed, 138 insertions(+), 97 deletions(-) rename matter/src/transport/{mgr.rs => core.rs} (76%) diff --git a/examples/onoff_light/src/main.rs b/examples/onoff_light/src/main.rs index 20b1cc9..baf2022 100644 --- a/examples/onoff_light/src/main.rs +++ b/examples/onoff_light/src/main.rs @@ -27,7 +27,6 @@ use matter::data_model::core::DataModel; use matter::data_model::device_types::DEV_TYPE_ON_OFF_LIGHT; use matter::data_model::objects::*; use matter::data_model::root_endpoint; -use matter::data_model::sdm::dev_att::DevAttDataFetcher; use matter::data_model::system_model::descriptor; use matter::error::Error; use matter::interaction_model::core::InteractionModel; @@ -36,7 +35,7 @@ use matter::persist; use matter::secure_channel::spake2p::VerifierData; use matter::transport::network::{Address, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use matter::transport::{ - mgr::RecvAction, mgr::TransportMgr, packet::MAX_RX_BUF_SIZE, packet::MAX_TX_BUF_SIZE, + core::RecvAction, core::Transport, packet::MAX_RX_BUF_SIZE, packet::MAX_TX_BUF_SIZE, udp::UdpListener, }; use matter::utils::select::EitherUnwrap; @@ -66,7 +65,7 @@ fn run() -> Result<(), Error> { info!( "Matter memory: mDNS={}, Transport={} (of which Matter={})", core::mem::size_of::(), - core::mem::size_of::(), + core::mem::size_of::(), core::mem::size_of::(), ); @@ -83,9 +82,11 @@ fn run() -> Result<(), Error> { //let (mut mdns, mdns_runner) = (matter::mdns::astro::AstroMdns::new()?, core::future::pending::pending()); //let (mut mdns, mdns_runner) = (matter::mdns::DummyMdns {}, core::future::pending::pending()); + let dev_att = dev_att::HardCodedDevAtt::new(); + let matter = Matter::new_default( // vid/pid should match those in the DAC - &BasicInfoConfig { + BasicInfoConfig { vid: 0xFFF1, pid: 0x8000, hw_ver: 2, @@ -94,12 +95,11 @@ fn run() -> Result<(), Error> { serial_no: "aabbccdd", device_name: "OnOff Light", }, + &dev_att, &mut mdns, matter::MATTER_PORT, ); - let dev_att = dev_att::HardCodedDevAtt::new(); - let psm_path = std::env::temp_dir().join("matter-iot"); info!("Persisting from/to {}", psm_path.display()); @@ -115,7 +115,9 @@ fn run() -> Result<(), Error> { matter.load_fabrics(data)?; } - matter.start( + let mut transport = Transport::new(&matter); + + transport.start( CommissioningData { // TODO: Hard-coded for now verifier: VerifierData::new_with_pw(123456, *matter.borrow()), @@ -125,10 +127,7 @@ fn run() -> Result<(), Error> { )?; let matter = &matter; - let dev_att = &dev_att; let mdns_runner = &mut mdns_runner; - - let mut transport = TransportMgr::new(matter); let transport = &mut transport; let mut io_fut = pin!(async move { @@ -165,7 +164,7 @@ fn run() -> Result<(), Error> { ], }; - let mut handler = handler(matter, dev_att); + let mut handler = handler(matter); let mut im = InteractionModel(DataModel::new(matter.borrow(), &node, &mut handler)); @@ -180,11 +179,11 @@ fn run() -> Result<(), Error> { } } - if let Some(data) = matter.store_fabrics(&mut buf)? { + if let Some(data) = transport.matter().store_fabrics(&mut buf)? { psm.store("fabrics", data)?; } - if let Some(data) = matter.store_acls(&mut buf)? { + if let Some(data) = transport.matter().store_acls(&mut buf)? { psm.store("acls", data)?; } } @@ -202,8 +201,8 @@ fn run() -> Result<(), Error> { Ok::<_, matter::error::Error>(()) } -fn handler<'a>(matter: &'a Matter<'a>, dev_att: &'a dyn DevAttDataFetcher) -> impl Handler + 'a { - root_endpoint::handler(0, dev_att, matter) +fn handler<'a>(matter: &'a Matter<'a>) -> impl Handler + 'a { + root_endpoint::handler(0, matter) .chain( 1, descriptor::ID, diff --git a/matter/src/core.rs b/matter/src/core.rs index fa960f7..dacddbd 100644 --- a/matter/src/core.rs +++ b/matter/src/core.rs @@ -19,7 +19,10 @@ use core::{borrow::Borrow, cell::RefCell}; use crate::{ acl::AclMgr, - data_model::{cluster_basic_information::BasicInfoConfig, sdm::failsafe::FailSafe}, + data_model::{ + cluster_basic_information::BasicInfoConfig, + sdm::{dev_att::DevAttDataFetcher, failsafe::FailSafe}, + }, error::*, fabric::FabricMgr, mdns::{Mdns, MdnsMgr}, @@ -48,17 +51,24 @@ pub struct Matter<'a> { pub mdns_mgr: RefCell>, pub epoch: Epoch, pub rand: Rand, - pub dev_det: &'a BasicInfoConfig<'a>, + pub dev_det: BasicInfoConfig<'a>, + pub dev_att: &'a dyn DevAttDataFetcher, + pub port: u16, } impl<'a> Matter<'a> { #[cfg(feature = "std")] #[inline(always)] - pub fn new_default(dev_det: &'a BasicInfoConfig, mdns: &'a mut dyn Mdns, port: u16) -> Self { + pub fn new_default( + dev_det: BasicInfoConfig<'a>, + dev_att: &'a dyn DevAttDataFetcher, + mdns: &'a mut dyn Mdns, + port: u16, + ) -> Self { use crate::utils::epoch::sys_epoch; use crate::utils::rand::sys_rand; - Self::new(dev_det, mdns, sys_epoch, sys_rand, port) + Self::new(dev_det, dev_att, mdns, sys_epoch, sys_rand, port) } /// Creates a new Matter object @@ -69,7 +79,8 @@ impl<'a> Matter<'a> { /// this object to return the device attestation details when queried upon. #[inline(always)] pub fn new( - dev_det: &'a BasicInfoConfig, + dev_det: BasicInfoConfig<'a>, + dev_att: &'a dyn DevAttDataFetcher, mdns: &'a mut dyn Mdns, epoch: Epoch, rand: Rand, @@ -90,11 +101,21 @@ impl<'a> Matter<'a> { epoch, rand, dev_det, + dev_att, + port, } } - pub fn dev_det(&self) -> &BasicInfoConfig { - self.dev_det + pub fn dev_det(&self) -> &BasicInfoConfig<'_> { + &self.dev_det + } + + pub fn dev_att(&self) -> &dyn DevAttDataFetcher { + self.dev_att + } + + pub fn port(&self) -> u16 { + self.port } pub fn load_fabrics(&self, data: &[u8]) -> Result<(), Error> { @@ -119,11 +140,15 @@ impl<'a> Matter<'a> { self.acl_mgr.borrow().is_changed() || self.fabric_mgr.borrow().is_changed() } - pub fn start(&self, dev_comm: CommissioningData, buf: &mut [u8]) -> Result<(), Error> { - let open_comm_window = self.fabric_mgr.borrow().is_empty(); - if open_comm_window { + pub fn start_comissioning( + &self, + dev_comm: CommissioningData, + buf: &mut [u8], + ) -> Result { + if !self.pase_mgr.borrow().is_pase_session_enabled() && self.fabric_mgr.borrow().is_empty() + { print_pairing_code_and_qr( - self.dev_det, + &self.dev_det, &dev_comm, DiscoveryCapabilities::default(), buf, @@ -134,9 +159,11 @@ impl<'a> Matter<'a> { dev_comm.discriminator, &mut self.mdns_mgr.borrow_mut(), )?; - } - Ok(()) + Ok(true) + } else { + Ok(false) + } } } diff --git a/matter/src/data_model/root_endpoint.rs b/matter/src/data_model/root_endpoint.rs index 7ad87fb..859d2bc 100644 --- a/matter/src/data_model/root_endpoint.rs +++ b/matter/src/data_model/root_endpoint.rs @@ -55,15 +55,11 @@ pub fn endpoint(id: EndptId) -> Endpoint<'static> { } } -pub fn handler<'a>( - endpoint_id: u16, - dev_att: &'a dyn DevAttDataFetcher, - matter: &'a Matter<'a>, -) -> RootEndpointHandler<'a> { +pub fn handler<'a>(endpoint_id: u16, matter: &'a Matter<'a>) -> RootEndpointHandler<'a> { wrap( endpoint_id, matter.dev_det(), - dev_att, + matter.dev_att(), matter.borrow(), matter.borrow(), matter.borrow(), diff --git a/matter/src/secure_channel/core.rs b/matter/src/secure_channel/core.rs index 7287ae0..2119691 100644 --- a/matter/src/secure_channel/core.rs +++ b/matter/src/secure_channel/core.rs @@ -15,7 +15,7 @@ * limitations under the License. */ -use core::cell::RefCell; +use core::{borrow::Borrow, cell::RefCell}; use crate::{ error::*, @@ -24,7 +24,7 @@ use crate::{ secure_channel::common::*, tlv, transport::{proto_ctx::ProtoCtx, session::CloneData}, - utils::rand::Rand, + utils::{epoch::Epoch, rand::Rand}, }; use log::{error, info}; use num; @@ -42,14 +42,32 @@ pub struct SecureChannel<'a> { impl<'a> SecureChannel<'a> { #[inline(always)] - pub fn new( + pub fn new< + T: Borrow> + + Borrow> + + Borrow>> + + Borrow + + Borrow, + >( + matter: &'a T, + ) -> Self { + Self::wrap( + matter.borrow(), + matter.borrow(), + matter.borrow(), + *matter.borrow(), + ) + } + + #[inline(always)] + pub fn wrap( pase: &'a RefCell, - fabric_mgr: &'a RefCell, + fabric: &'a RefCell, mdns: &'a RefCell>, rand: Rand, ) -> Self { - SecureChannel { - case: Case::new(fabric_mgr, rand), + Self { + case: Case::new(fabric, rand), pase, mdns, } diff --git a/matter/src/secure_channel/pake.rs b/matter/src/secure_channel/pake.rs index ab09512..b5a29a2 100644 --- a/matter/src/secure_channel/pake.rs +++ b/matter/src/secure_channel/pake.rs @@ -59,6 +59,10 @@ impl PaseMgr { } } + pub fn is_pase_session_enabled(&self) -> bool { + matches!(&self.state, PaseMgrState::Enabled(_, _, _)) + } + pub fn enable_pase_session( &mut self, verifier: VerifierData, diff --git a/matter/src/transport/mgr.rs b/matter/src/transport/core.rs similarity index 76% rename from matter/src/transport/mgr.rs rename to matter/src/transport/core.rs index eeff6ff..1d02bc0 100644 --- a/matter/src/transport/mgr.rs +++ b/matter/src/transport/core.rs @@ -15,22 +15,14 @@ * limitations under the License. */ -use core::borrow::Borrow; -use core::cell::RefCell; - use log::info; -use crate::error::*; -use crate::fabric::FabricMgr; -use crate::mdns::MdnsMgr; -use crate::secure_channel::pake::PaseMgr; +use crate::{error::*, CommissioningData, Matter}; use crate::secure_channel::common::PROTO_ID_SECURE_CHANNEL; use crate::secure_channel::core::SecureChannel; use crate::transport::mrp::ReliableMessage; use crate::transport::{exchange, network::Address, packet::Packet}; -use crate::utils::epoch::Epoch; -use crate::utils::rand::Rand; use super::proto_ctx::ProtoCtx; use super::session::CloneData; @@ -50,7 +42,7 @@ pub enum RecvAction<'r, 'p> { } pub struct RecvCompletion<'r, 'a, 'p> { - mgr: &'r mut TransportMgr<'a>, + transport: &'r mut Transport<'a>, rx: Packet<'p>, tx: Packet<'p>, state: RecvState, @@ -69,20 +61,25 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> { } fn maybe_next_action(&mut self) -> Result>>, Error> { - self.mgr.exch_mgr.purge(); + self.transport.exch_mgr.purge(); self.tx.reset(); let (state, next) = match core::mem::replace(&mut self.state, RecvState::New) { RecvState::New => { - self.mgr.exch_mgr.get_sess_mgr().decode(&mut self.rx)?; + self.transport + .exch_mgr + .get_sess_mgr() + .decode(&mut self.rx)?; (RecvState::OpenExchange, None) } - RecvState::OpenExchange => match self.mgr.exch_mgr.recv(&mut self.rx) { + RecvState::OpenExchange => match self.transport.exch_mgr.recv(&mut self.rx) { Ok(Some(exch_ctx)) => { if self.rx.get_proto_id() == PROTO_ID_SECURE_CHANNEL { let mut proto_ctx = ProtoCtx::new(exch_ctx, &self.rx, &mut self.tx); - let (reply, clone_data) = self.mgr.secure_channel.handle(&mut proto_ctx)?; + let mut secure_channel = SecureChannel::new(self.transport.matter); + + let (reply, clone_data) = secure_channel.handle(&mut proto_ctx)?; let state = if let Some(clone_data) = clone_data { RecvState::AddSession(clone_data) @@ -115,15 +112,17 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> { _ => Err(e)?, }, }, - RecvState::AddSession(clone_data) => match self.mgr.exch_mgr.add_session(&clone_data) { - Ok(_) => (RecvState::Ack, None), - Err(e) => match e.code() { - ErrorCode::NoSpace => (RecvState::EvictSession2(clone_data), None), - _ => Err(e)?, - }, - }, + RecvState::AddSession(clone_data) => { + match self.transport.exch_mgr.add_session(&clone_data) { + Ok(_) => (RecvState::Ack, None), + Err(e) => match e.code() { + ErrorCode::NoSpace => (RecvState::EvictSession2(clone_data), None), + _ => Err(e)?, + }, + } + } RecvState::EvictSession => { - if self.mgr.exch_mgr.evict_session(&mut self.tx)? { + if self.transport.exch_mgr.evict_session(&mut self.tx)? { ( RecvState::OpenExchange, Some(Some(RecvAction::Send(self.tx.peer, self.tx.as_slice()))), @@ -133,7 +132,7 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> { } } RecvState::EvictSession2(clone_data) => { - if self.mgr.exch_mgr.evict_session(&mut self.tx)? { + if self.transport.exch_mgr.evict_session(&mut self.tx)? { ( RecvState::AddSession(clone_data), Some(Some(RecvAction::Send(self.tx.peer, self.tx.as_slice()))), @@ -143,12 +142,12 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> { } } RecvState::Ack => { - if let Some(exch_id) = self.mgr.exch_mgr.pending_ack() { + if let Some(exch_id) = self.transport.exch_mgr.pending_ack() { info!("Sending MRP Standalone ACK for exch {}", exch_id); ReliableMessage::prepare_ack(exch_id, &mut self.tx); - if self.mgr.exch_mgr.send(exch_id, &mut self.tx)? { + if self.transport.exch_mgr.send(exch_id, &mut self.tx)? { ( RecvState::Ack, Some(Some(RecvAction::Send(self.tx.peer, self.tx.as_slice()))), @@ -176,7 +175,7 @@ pub enum NotifyAction<'r, 'p> { pub struct NotifyCompletion<'r, 'a, 'p> { // TODO - _mgr: &'r mut TransportMgr<'a>, + _transport: &'r mut Transport<'a>, _rx: &'r mut Packet<'p>, _tx: &'r mut Packet<'p>, _state: NotifyState, @@ -199,38 +198,35 @@ impl<'r, 'a, 'p> NotifyCompletion<'r, 'a, 'p> { } } -pub struct TransportMgr<'a> { +pub struct Transport<'a> { + matter: &'a Matter<'a>, exch_mgr: exchange::ExchangeMgr, - secure_channel: SecureChannel<'a>, } -impl<'a> TransportMgr<'a> { - pub fn new< - T: Borrow> - + Borrow> - + Borrow>> - + Borrow - + Borrow, - >( - matter: &'a T, - ) -> Self { - Self::wrap( - SecureChannel::new( - matter.borrow(), - matter.borrow(), - matter.borrow(), - *matter.borrow(), - ), - *matter.borrow(), - *matter.borrow(), - ) +impl<'a> Transport<'a> { + #[inline(always)] + pub fn new(matter: &'a Matter<'a>) -> Self { + let epoch = matter.epoch; + let rand = matter.rand; + + Self { + matter, + exch_mgr: exchange::ExchangeMgr::new(epoch, rand), + } } - pub fn wrap(secure_channel: SecureChannel<'a>, epoch: Epoch, rand: Rand) -> Self { - Self { - exch_mgr: exchange::ExchangeMgr::new(epoch, rand), - secure_channel, + pub fn matter(&self) -> &Matter<'a> { + &self.matter + } + + pub fn start(&mut self, dev_comm: CommissioningData, buf: &mut [u8]) -> Result<(), Error> { + info!("Starting Matter transport"); + + if self.matter().start_comissioning(dev_comm, buf)? { + info!("Comissioning started"); } + + Ok(()) } pub fn recv<'r, 'p>( @@ -245,7 +241,7 @@ impl<'a> TransportMgr<'a> { rx.peer = addr; RecvCompletion { - mgr: self, + transport: self, rx, tx, state: RecvState::New, diff --git a/matter/src/transport/exchange.rs b/matter/src/transport/exchange.rs index 04b63db..4910dbc 100644 --- a/matter/src/transport/exchange.rs +++ b/matter/src/transport/exchange.rs @@ -279,6 +279,7 @@ pub struct ExchangeMgr { pub const MAX_MRP_ENTRIES: usize = 4; impl ExchangeMgr { + #[inline(always)] pub fn new(epoch: Epoch, rand: Rand) -> Self { Self { sess_mgr: SessionMgr::new(epoch, rand), diff --git a/matter/src/transport/mod.rs b/matter/src/transport/mod.rs index 1a81c75..18957be 100644 --- a/matter/src/transport/mod.rs +++ b/matter/src/transport/mod.rs @@ -15,9 +15,9 @@ * limitations under the License. */ +pub mod core; mod dedup; pub mod exchange; -pub mod mgr; pub mod mrp; pub mod network; pub mod packet; diff --git a/matter/tests/common/im_engine.rs b/matter/tests/common/im_engine.rs index ce608c5..70b2aca 100644 --- a/matter/tests/common/im_engine.rs +++ b/matter/tests/common/im_engine.rs @@ -65,7 +65,7 @@ const BASIC_INFO: BasicInfoConfig<'static> = BasicInfoConfig { device_name: "Test Device", }; -pub struct DummyDevAtt {} +struct DummyDevAtt; impl DevAttDataFetcher for DummyDevAtt { fn get_devatt_data(&self, _data_type: DataType, _data: &mut [u8]) -> Result { @@ -110,7 +110,7 @@ pub fn matter(mdns: &mut dyn Mdns) -> Matter<'_> { #[cfg(not(feature = "std"))] use matter::utils::epoch::dummy_epoch as epoch; - Matter::new(&BASIC_INFO, mdns, epoch, dummy_rand, 5540) + Matter::new(BASIC_INFO, &DummyDevAtt, mdns, epoch, dummy_rand, 5540) } /// An Interaction Model Engine to facilitate easy testing @@ -161,7 +161,7 @@ impl<'a> ImEngine<'a> { }, ], }, - root_endpoint::handler(0, &DummyDevAtt {}, matter) + root_endpoint::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()))