Simplify main user-facing API

This commit is contained in:
ivmarkov 2023-06-09 07:47:49 +00:00
parent 8e9d8887da
commit 1b879f1a5b
9 changed files with 138 additions and 97 deletions

View file

@ -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::<Mdns>(),
core::mem::size_of::<TransportMgr>(),
core::mem::size_of::<Transport>(),
core::mem::size_of::<Matter>(),
);
@ -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,

View file

@ -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<MdnsMgr<'a>>,
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<bool, Error> {
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)
}
}
}

View file

@ -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(),

View file

@ -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<RefCell<FabricMgr>>
+ Borrow<RefCell<PaseMgr>>
+ Borrow<RefCell<MdnsMgr<'a>>>
+ Borrow<Epoch>
+ Borrow<Rand>,
>(
matter: &'a T,
) -> Self {
Self::wrap(
matter.borrow(),
matter.borrow(),
matter.borrow(),
*matter.borrow(),
)
}
#[inline(always)]
pub fn wrap(
pase: &'a RefCell<PaseMgr>,
fabric_mgr: &'a RefCell<FabricMgr>,
fabric: &'a RefCell<FabricMgr>,
mdns: &'a RefCell<MdnsMgr<'a>>,
rand: Rand,
) -> Self {
SecureChannel {
case: Case::new(fabric_mgr, rand),
Self {
case: Case::new(fabric, rand),
pase,
mdns,
}

View file

@ -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,

View file

@ -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<Option<Option<RecvAction<'_, 'p>>>, 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<RefCell<FabricMgr>>
+ Borrow<RefCell<PaseMgr>>
+ Borrow<RefCell<MdnsMgr<'a>>>
+ Borrow<Epoch>
+ Borrow<Rand>,
>(
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,

View file

@ -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),

View file

@ -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;

View file

@ -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<usize, Error> {
@ -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()))