On-off example now buildable

This commit is contained in:
ivmarkov 2023-04-24 11:34:32 +00:00
parent 17002db7e1
commit a7ca17fabc
10 changed files with 175 additions and 84 deletions

View file

@ -15,4 +15,4 @@
* limitations under the License. * limitations under the License.
*/ */
// TODO pub mod dev_att; pub mod dev_att;

View file

@ -15,41 +15,114 @@
* limitations under the License. * limitations under the License.
*/ */
// TODO use std::borrow::Borrow;
// mod dev_att;
// use matter::core::{self, CommissioningData}; use matter::core::{CommissioningData, Matter};
// use matter::data_model::cluster_basic_information::BasicInfoConfig; use matter::data_model::cluster_basic_information::BasicInfoConfig;
// use matter::data_model::device_types::device_type_add_on_off_light; use matter::data_model::cluster_on_off;
// use matter::secure_channel::spake2p::VerifierData; 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::interaction_model::core::InteractionModel;
use matter::secure_channel::spake2p::VerifierData;
use matter::transport::{
mgr::RecvAction, mgr::TransportMgr, packet::Packet, packet::MAX_RX_BUF_SIZE,
packet::MAX_TX_BUF_SIZE, udp::UdpListener,
};
mod dev_att;
fn main() { fn main() {
// env_logger::init(); env_logger::init();
// let comm_data = CommissioningData {
// // TODO: Hard-coded for now
// verifier: VerifierData::new_with_pw(123456),
// discriminator: 250,
// };
// // vid/pid should match those in the DAC // vid/pid should match those in the DAC
// let dev_info = BasicInfoConfig { let dev_info = BasicInfoConfig {
// vid: 0xFFF1, vid: 0xFFF1,
// pid: 0x8000, pid: 0x8000,
// hw_ver: 2, hw_ver: 2,
// sw_ver: 1, sw_ver: 1,
// sw_ver_str: "1".to_string(), sw_ver_str: "1",
// serial_no: "aabbccdd".to_string(), serial_no: "aabbccdd",
// device_name: "OnOff Light".to_string(), device_name: "OnOff Light",
// }; };
// let dev_att = Box::new(dev_att::HardCodedDevAtt::new());
// let mut matter = core::Matter::new(dev_info, dev_att, comm_data).unwrap(); let mut mdns = matter::sys::LinuxMdns::new().unwrap();
// let dm = matter.get_data_model();
// {
// let mut node = dm.node.write().unwrap();
// let endpoint = device_type_add_on_off_light(&mut node).unwrap();
// println!("Added OnOff Light Device type at endpoint id: {}", endpoint);
// println!("Data Model now is: {}", node);
// }
// matter.start_daemon().unwrap(); let matter = Matter::new_default(&dev_info, &mut mdns);
let dev_att = dev_att::HardCodedDevAtt::new();
matter
.start::<4096>(
CommissioningData {
// TODO: Hard-coded for now
verifier: VerifierData::new_with_pw(123456, *matter.borrow()),
discriminator: 250,
},
&mut [0; 4096],
)
.unwrap();
let matter = &matter;
let dev_att = &dev_att;
let mut transport = TransportMgr::new(matter);
smol::block_on(async move {
let udp = UdpListener::new().await.unwrap();
loop {
let mut rx_buf = [0; MAX_RX_BUF_SIZE];
let mut tx_buf = [0; MAX_TX_BUF_SIZE];
let (len, addr) = udp.recv(&mut rx_buf).await.unwrap();
let mut rx = Packet::new_rx(&mut rx_buf[..len]);
let mut tx = Packet::new_tx(&mut tx_buf);
let mut completion = transport.recv(addr, &mut rx, &mut tx);
while let Some(action) = completion.next_action().unwrap() {
match action {
RecvAction::Send(addr, buf) => {
udp.send(addr, buf).await.unwrap();
}
RecvAction::Interact(mut ctx) => {
let node = Node {
id: 0,
endpoints: &[
root_endpoint::endpoint(0),
Endpoint {
id: 1,
device_type: DEV_TYPE_ON_OFF_LIGHT,
clusters: &[cluster_on_off::CLUSTER],
},
],
};
let mut handler = handler(matter, dev_att);
let mut im =
InteractionModel(DataModel::new(matter.borrow(), &node, &mut handler));
if im.handle(&mut ctx).unwrap() {
if let Some(addr) = ctx.send().unwrap() {
udp.send(addr, ctx.tx.as_slice()).await.unwrap();
}
}
}
}
}
}
});
}
fn handler<'a>(matter: &'a Matter<'a>, dev_att: &'a dyn DevAttDataFetcher) -> impl Handler + 'a {
root_endpoint::handler(0, dev_att, matter).chain(
1,
cluster_on_off::ID,
cluster_on_off::OnOffCluster::new(*matter.borrow()),
)
} }

View file

@ -15,7 +15,7 @@ name = "matter"
path = "src/lib.rs" path = "src/lib.rs"
[features] [features]
default = ["std", "crypto_mbedtls"] default = ["std", "crypto_mbedtls", "nightly"]
std = ["alloc", "env_logger", "chrono", "rand", "qrcode", "smol"] std = ["alloc", "env_logger", "chrono", "rand", "qrcode", "smol"]
alloc = [] alloc = []
nightly = [] nightly = []

View file

@ -99,7 +99,7 @@ impl<'a> Matter<'a> {
} }
pub fn start<const N: usize>( pub fn start<const N: usize>(
&mut self, &self,
dev_comm: CommissioningData, dev_comm: CommissioningData,
buf: &mut [u8], buf: &mut [u8],
) -> Result<(), Error> { ) -> Result<(), Error> {

View file

@ -12,7 +12,7 @@ use crate::{
use super::{ use super::{
cluster_basic_information::{self, BasicInfoCluster, BasicInfoConfig}, cluster_basic_information::{self, BasicInfoCluster, BasicInfoConfig},
objects::{Cluster, EmptyHandler}, objects::{Cluster, EmptyHandler, Endpoint, EndptId},
sdm::{ sdm::{
admin_commissioning::{self, AdminCommCluster}, admin_commissioning::{self, AdminCommCluster},
dev_att::DevAttDataFetcher, dev_att::DevAttDataFetcher,
@ -47,6 +47,14 @@ pub const CLUSTERS: [Cluster<'static>; 7] = [
access_control::CLUSTER, access_control::CLUSTER,
]; ];
pub fn endpoint(id: EndptId) -> Endpoint<'static> {
Endpoint {
id,
device_type: super::device_types::DEV_TYPE_ROOT_NODE,
clusters: &CLUSTERS,
}
}
pub fn handler<'a>( pub fn handler<'a>(
endpoint_id: u16, endpoint_id: u16,
dev_att: &'a dyn DevAttDataFetcher, dev_att: &'a dyn DevAttDataFetcher,

View file

@ -710,14 +710,14 @@ impl ResumeSubscribeReq {
} }
pub trait InteractionHandler { pub trait InteractionHandler {
fn handle<'a>(&mut self, ctx: &'a mut ProtoCtx) -> Result<Option<&'a [u8]>, Error>; fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<bool, Error>;
} }
impl<T> InteractionHandler for &mut T impl<T> InteractionHandler for &mut T
where where
T: InteractionHandler, T: InteractionHandler,
{ {
fn handle<'a>(&mut self, ctx: &'a mut ProtoCtx) -> Result<Option<&'a [u8]>, Error> { fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<bool, Error> {
(**self).handle(ctx) (**self).handle(ctx)
} }
} }
@ -728,7 +728,7 @@ impl<T> InteractionModel<T>
where where
T: DataHandler, T: DataHandler,
{ {
pub fn handle<'a>(&mut self, ctx: &'a mut ProtoCtx) -> Result<Option<&'a [u8]>, Error> { pub fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<bool, Error> {
let mut transaction = Transaction::new(&mut ctx.exch_ctx); let mut transaction = Transaction::new(&mut ctx.exch_ctx);
let reply = let reply =
@ -738,7 +738,7 @@ where
true true
}; };
Ok(reply.then_some(ctx.tx.as_slice())) Ok(reply)
} }
} }
@ -747,10 +747,7 @@ impl<T> InteractionModel<T>
where where
T: crate::data_model::core::asynch::AsyncDataHandler, T: crate::data_model::core::asynch::AsyncDataHandler,
{ {
pub async fn handle_async<'a>( pub async fn handle_async<'a>(&mut self, ctx: &mut ProtoCtx<'_, '_>) -> Result<bool, Error> {
&mut self,
ctx: &'a mut ProtoCtx<'_, '_>,
) -> Result<Option<&'a [u8]>, Error> {
let mut transaction = Transaction::new(&mut ctx.exch_ctx); let mut transaction = Transaction::new(&mut ctx.exch_ctx);
let reply = let reply =
@ -760,7 +757,7 @@ where
true true
}; };
Ok(reply.then_some(ctx.tx.as_slice())) Ok(reply)
} }
} }
@ -768,7 +765,7 @@ impl<T> InteractionHandler for InteractionModel<T>
where where
T: DataHandler, T: DataHandler,
{ {
fn handle<'a>(&mut self, ctx: &'a mut ProtoCtx) -> Result<Option<&'a [u8]>, Error> { fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<bool, Error> {
InteractionModel::handle(self, ctx) InteractionModel::handle(self, ctx)
} }
} }
@ -782,20 +779,14 @@ pub mod asynch {
use super::InteractionModel; use super::InteractionModel;
pub trait AsyncInteractionHandler { pub trait AsyncInteractionHandler {
async fn handle<'a>( async fn handle(&mut self, ctx: &mut ProtoCtx<'_, '_>) -> Result<bool, Error>;
&mut self,
ctx: &'a mut ProtoCtx<'_, '_>,
) -> Result<Option<&'a [u8]>, Error>;
} }
impl<T> AsyncInteractionHandler for &mut T impl<T> AsyncInteractionHandler for &mut T
where where
T: AsyncInteractionHandler, T: AsyncInteractionHandler,
{ {
async fn handle<'a>( async fn handle(&mut self, ctx: &mut ProtoCtx<'_, '_>) -> Result<bool, Error> {
&mut self,
ctx: &'a mut ProtoCtx<'_, '_>,
) -> Result<Option<&'a [u8]>, Error> {
(**self).handle(ctx).await (**self).handle(ctx).await
} }
} }
@ -804,10 +795,7 @@ pub mod asynch {
where where
T: AsyncDataHandler, T: AsyncDataHandler,
{ {
async fn handle<'a>( async fn handle(&mut self, ctx: &mut ProtoCtx<'_, '_>) -> Result<bool, Error> {
&mut self,
ctx: &'a mut ProtoCtx<'_, '_>,
) -> Result<Option<&'a [u8]>, Error> {
InteractionModel::handle_async(self, ctx).await InteractionModel::handle_async(self, ctx).await
} }
} }

View file

@ -31,7 +31,10 @@ use crate::utils::rand::Rand;
use heapless::LinearMap; use heapless::LinearMap;
use super::session::CloneData; use super::session::CloneData;
use super::{mrp::ReliableMessage, packet::Packet, session::SessionHandle, session::SessionMgr}; use super::{
mrp::ReliableMessage, network::Address, packet::Packet, session::SessionHandle,
session::SessionMgr,
};
pub struct ExchangeCtx<'a> { pub struct ExchangeCtx<'a> {
pub exch: &'a mut Exchange, pub exch: &'a mut Exchange,
@ -40,7 +43,7 @@ pub struct ExchangeCtx<'a> {
} }
impl<'a> ExchangeCtx<'a> { impl<'a> ExchangeCtx<'a> {
pub fn send(&mut self, tx: &mut Packet) -> Result<(), Error> { pub fn send(&mut self, tx: &mut Packet) -> Result<Option<Address>, Error> {
self.exch.send(tx, &mut self.sess) self.exch.send(tx, &mut self.sess)
} }
} }
@ -198,10 +201,10 @@ impl Exchange {
&mut self, &mut self,
tx: &mut Packet, tx: &mut Packet,
session: &mut SessionHandle, session: &mut SessionHandle,
) -> Result<(), Error> { ) -> Result<Option<Address>, Error> {
if self.state == State::Terminate { if self.state == State::Terminate {
info!("Skipping tx for terminated exchange {}", self.id); info!("Skipping tx for terminated exchange {}", self.id);
return Ok(()); return Ok(None);
} }
trace!("payload: {:x?}", tx.as_mut_slice()); trace!("payload: {:x?}", tx.as_mut_slice());
@ -219,7 +222,9 @@ impl Exchange {
session.pre_send(tx)?; session.pre_send(tx)?;
self.mrp.pre_send(tx)?; self.mrp.pre_send(tx)?;
session.send(tx) session.send(tx)?;
Ok(Some(session.get_peer_addr()))
} }
} }
@ -354,11 +359,13 @@ impl ExchangeMgr {
} }
} }
pub fn send(&mut self, exch_id: u16, tx: &mut Packet) -> Result<(), Error> { pub fn send(&mut self, exch_id: u16, tx: &mut Packet) -> Result<Address, Error> {
let exchange = let exchange =
ExchangeMgr::_get_with_id(&mut self.exchanges, exch_id).ok_or(Error::NoExchange)?; ExchangeMgr::_get_with_id(&mut self.exchanges, exch_id).ok_or(Error::NoExchange)?;
let mut session = self.sess_mgr.get_session_handle(exchange.sess_idx); let mut session = self.sess_mgr.get_session_handle(exchange.sess_idx);
exchange.send(tx, &mut session) exchange.send(tx, &mut session)?;
Ok(session.get_peer_addr())
} }
pub fn purge(&mut self) { pub fn purge(&mut self) {
@ -381,7 +388,7 @@ impl ExchangeMgr {
.map(|(exch_id, _)| *exch_id) .map(|(exch_id, _)| *exch_id)
} }
pub fn evict_session(&mut self, tx: &mut Packet) -> Result<bool, Error> { pub fn evict_session(&mut self, tx: &mut Packet) -> Result<Option<Address>, Error> {
if let Some(index) = self.sess_mgr.get_session_for_eviction() { if let Some(index) = self.sess_mgr.get_session_for_eviction() {
info!("Sessions full, vacating session with index: {}", index); info!("Sessions full, vacating session with index: {}", index);
// If we enter here, we have an LRU session that needs to be reclaimed // If we enter here, we have an LRU session that needs to be reclaimed
@ -423,11 +430,14 @@ impl ExchangeMgr {
// Remove from exchange list // Remove from exchange list
self.exchanges.remove(&exch_id); self.exchanges.remove(&exch_id);
} }
let addr = session.get_peer_addr();
self.sess_mgr.remove(index); self.sess_mgr.remove(index);
Ok(true) Ok(Some(addr))
} else { } else {
Ok(false) Ok(None)
} }
} }
@ -561,7 +571,7 @@ mod tests {
let mut buf = [0; MAX_TX_BUF_SIZE]; let mut buf = [0; MAX_TX_BUF_SIZE];
let tx = &mut Packet::new_tx(&mut buf); let tx = &mut Packet::new_tx(&mut buf);
let evicted = mgr.evict_session(tx).unwrap(); let evicted = mgr.evict_session(tx).unwrap();
assert!(evicted); assert!(evicted.is_some());
let session = mgr let session = mgr
.add_session(&get_clone_data(new_peer_sess_id, new_local_sess_id)) .add_session(&get_clone_data(new_peer_sess_id, new_local_sess_id))

View file

@ -32,6 +32,7 @@ use crate::transport::{exchange, packet::Packet};
use crate::utils::epoch::{Epoch, UtcCalendar}; use crate::utils::epoch::{Epoch, UtcCalendar};
use crate::utils::rand::Rand; use crate::utils::rand::Rand;
use super::network::Address;
use super::proto_ctx::ProtoCtx; use super::proto_ctx::ProtoCtx;
use super::session::CloneData; use super::session::CloneData;
@ -45,12 +46,13 @@ enum RecvState {
} }
pub enum RecvAction<'r, 'p> { pub enum RecvAction<'r, 'p> {
Send(&'r [u8]), Send(Address, &'r [u8]),
Interact(ProtoCtx<'r, 'p>), Interact(ProtoCtx<'r, 'p>),
} }
pub struct RecvCompletion<'r, 'a, 'p> { pub struct RecvCompletion<'r, 'a, 'p> {
mgr: &'r mut TransportMgr<'a>, mgr: &'r mut TransportMgr<'a>,
addr: Address, // TODO: Not used yet
rx: &'r mut Packet<'p>, rx: &'r mut Packet<'p>,
tx: &'r mut Packet<'p>, tx: &'r mut Packet<'p>,
state: RecvState, state: RecvState,
@ -90,9 +92,10 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> {
self.state = RecvState::Ack; self.state = RecvState::Ack;
} }
if reply { let addr = if reply { proto_ctx.send()? } else { None };
proto_ctx.send()?;
Ok(Some(Some(RecvAction::Send(self.tx.as_slice())))) if let Some(addr) = addr {
Ok(Some(Some(RecvAction::Send(addr, self.tx.as_slice()))))
} else { } else {
Ok(None) Ok(None)
} }
@ -125,14 +128,22 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> {
Err(err) => Err(err), Err(err) => Err(err),
}, },
RecvState::EvictSession => { RecvState::EvictSession => {
self.mgr.exch_mgr.evict_session(self.tx)?; let addr = self.mgr.exch_mgr.evict_session(self.tx)?;
self.state = RecvState::OpenExchange; self.state = RecvState::OpenExchange;
Ok(Some(Some(RecvAction::Send(self.tx.as_slice())))) if let Some(addr) = addr {
Ok(Some(Some(RecvAction::Send(addr, self.tx.as_slice()))))
} else {
Ok(None)
}
} }
RecvState::EvictSession2(clone_data) => { RecvState::EvictSession2(clone_data) => {
self.mgr.exch_mgr.evict_session(self.tx)?; let addr = self.mgr.exch_mgr.evict_session(self.tx)?;
self.state = RecvState::AddSession(clone_data); self.state = RecvState::AddSession(clone_data);
Ok(Some(Some(RecvAction::Send(self.tx.as_slice())))) if let Some(addr) = addr {
Ok(Some(Some(RecvAction::Send(addr, self.tx.as_slice()))))
} else {
Ok(None)
}
} }
RecvState::Ack => { RecvState::Ack => {
if let Some(exch_id) = self.mgr.exch_mgr.pending_ack() { if let Some(exch_id) = self.mgr.exch_mgr.pending_ack() {
@ -140,8 +151,8 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> {
ReliableMessage::prepare_ack(exch_id, self.tx); ReliableMessage::prepare_ack(exch_id, self.tx);
self.mgr.exch_mgr.send(exch_id, self.tx)?; let addr = self.mgr.exch_mgr.send(exch_id, self.tx)?;
Ok(Some(Some(RecvAction::Send(self.tx.as_slice())))) Ok(Some(Some(RecvAction::Send(addr, self.tx.as_slice()))))
} else { } else {
Ok(Some(None)) Ok(Some(None))
} }
@ -220,11 +231,13 @@ impl<'a> TransportMgr<'a> {
pub fn recv<'r, 'p>( pub fn recv<'r, 'p>(
&'r mut self, &'r mut self,
addr: Address,
rx: &'r mut Packet<'p>, rx: &'r mut Packet<'p>,
tx: &'r mut Packet<'p>, tx: &'r mut Packet<'p>,
) -> RecvCompletion<'r, 'a, 'p> { ) -> RecvCompletion<'r, 'a, 'p> {
RecvCompletion { RecvCompletion {
mgr: self, mgr: self,
addr,
rx, rx,
tx, tx,
state: RecvState::New, state: RecvState::New,

View file

@ -18,6 +18,7 @@
use crate::error::Error; use crate::error::Error;
use super::exchange::ExchangeCtx; use super::exchange::ExchangeCtx;
use super::network::Address;
use super::packet::Packet; use super::packet::Packet;
/// This is the context in which a receive packet is being processed /// This is the context in which a receive packet is being processed
@ -35,9 +36,7 @@ impl<'a, 'b> ProtoCtx<'a, 'b> {
Self { exch_ctx, rx, tx } Self { exch_ctx, rx, tx }
} }
pub fn send(&mut self) -> Result<&[u8], Error> { pub fn send(&mut self) -> Result<Option<Address>, Error> {
self.exch_ctx.exch.send(self.tx, &mut self.exch_ctx.sess)?; self.exch_ctx.exch.send(self.tx, &mut self.exch_ctx.sess)
Ok(self.tx.as_slice())
} }
} }

View file

@ -48,7 +48,7 @@ impl UdpListener {
Ok((size, Address::Udp(addr))) Ok((size, Address::Udp(addr)))
} }
pub async fn send(&self, out_buf: &[u8], addr: Address) -> Result<usize, Error> { pub async fn send(&self, addr: Address, out_buf: &[u8]) -> Result<usize, Error> {
match addr { match addr {
Address::Udp(addr) => self.socket.send_to(out_buf, addr).await.map_err(|e| { Address::Udp(addr) => self.socket.send_to(out_buf, addr).await.map_err(|e| {
info!("Error on the network: {:?}", e); info!("Error on the network: {:?}", e);