New helper APIs in Transport
This commit is contained in:
parent
0d73ba74ee
commit
24cdf079a6
2 changed files with 196 additions and 165 deletions
|
@ -17,13 +17,23 @@
|
||||||
|
|
||||||
use core::{borrow::Borrow, cell::RefCell};
|
use core::{borrow::Borrow, cell::RefCell};
|
||||||
|
|
||||||
use crate::{error::ErrorCode, secure_channel::common::OpCode, Matter};
|
|
||||||
use embassy_futures::select::select;
|
use embassy_futures::select::select;
|
||||||
|
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Channel};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use log::info;
|
|
||||||
|
use log::{error, info, warn};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Error, secure_channel::common::PROTO_ID_SECURE_CHANNEL, transport::packet::Packet,
|
alloc,
|
||||||
|
data_model::{core::DataModel, objects::DataModelHandler},
|
||||||
|
error::{Error, ErrorCode},
|
||||||
|
interaction_model::core::PROTO_ID_INTERACTION_MODEL,
|
||||||
|
secure_channel::{
|
||||||
|
common::{OpCode, PROTO_ID_SECURE_CHANNEL},
|
||||||
|
core::SecureChannel,
|
||||||
|
},
|
||||||
|
transport::packet::Packet,
|
||||||
|
Matter,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
|
@ -32,6 +42,8 @@ use super::{
|
||||||
MAX_EXCHANGES,
|
MAX_EXCHANGES,
|
||||||
},
|
},
|
||||||
mrp::ReliableMessage,
|
mrp::ReliableMessage,
|
||||||
|
packet::{MAX_RX_BUF_SIZE, MAX_RX_STATUS_BUF_SIZE, MAX_TX_BUF_SIZE},
|
||||||
|
pipe::{Chunk, Pipe},
|
||||||
session::SessionMgr,
|
session::SessionMgr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -83,6 +95,165 @@ impl<'a> Transport<'a> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub async fn handle_tx(&self, tx_pipe: &Pipe<'_>) -> Result<(), Error> {
|
||||||
|
loop {
|
||||||
|
loop {
|
||||||
|
{
|
||||||
|
let mut data = tx_pipe.data.lock().await;
|
||||||
|
|
||||||
|
if data.chunk.is_none() {
|
||||||
|
let mut tx = alloc!(Packet::new_tx(data.buf));
|
||||||
|
|
||||||
|
if self.pull_tx(&mut tx).await? {
|
||||||
|
data.chunk = Some(Chunk {
|
||||||
|
start: tx.get_writebuf()?.get_start(),
|
||||||
|
end: tx.get_writebuf()?.get_tail(),
|
||||||
|
addr: tx.peer,
|
||||||
|
});
|
||||||
|
tx_pipe.data_supplied_notification.signal(());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tx_pipe.data_consumed_notification.wait().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.wait_tx().await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub async fn handle_rx_multiplex<'t, 'e, const N: usize>(
|
||||||
|
&'t self,
|
||||||
|
rx_pipe: &Pipe<'_>,
|
||||||
|
construction_notification: &'e Notification,
|
||||||
|
channel: &Channel<NoopRawMutex, ExchangeCtr<'e>, N>,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
't: 'e,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
info!("Transport: waiting for incoming packets");
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut data = rx_pipe.data.lock().await;
|
||||||
|
|
||||||
|
if let Some(chunk) = data.chunk {
|
||||||
|
let mut rx = alloc!(Packet::new_rx(&mut data.buf[chunk.start..chunk.end]));
|
||||||
|
rx.peer = chunk.addr;
|
||||||
|
|
||||||
|
if let Some(exchange_ctr) =
|
||||||
|
self.process_rx(construction_notification, &mut rx)?
|
||||||
|
{
|
||||||
|
let exchange_id = exchange_ctr.id().clone();
|
||||||
|
|
||||||
|
info!("Transport: got new exchange: {:?}", exchange_id);
|
||||||
|
|
||||||
|
channel.send(exchange_ctr).await;
|
||||||
|
info!("Transport: exchange sent");
|
||||||
|
|
||||||
|
self.wait_construction(construction_notification, &rx, &exchange_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
info!("Transport: exchange started");
|
||||||
|
}
|
||||||
|
|
||||||
|
data.chunk = None;
|
||||||
|
rx_pipe.data_consumed_notification.signal(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rx_pipe.data_supplied_notification.wait().await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unreachable_code)]
|
||||||
|
Ok::<_, Error>(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
pub async fn exchange_handler<const N: usize, H>(
|
||||||
|
&self,
|
||||||
|
tx_buf: &mut [u8; MAX_TX_BUF_SIZE],
|
||||||
|
rx_buf: &mut [u8; MAX_RX_BUF_SIZE],
|
||||||
|
sx_buf: &mut [u8; MAX_RX_STATUS_BUF_SIZE],
|
||||||
|
handler_id: impl core::fmt::Display,
|
||||||
|
channel: &Channel<NoopRawMutex, ExchangeCtr<'_>, N>,
|
||||||
|
handler: &H,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
H: DataModelHandler,
|
||||||
|
{
|
||||||
|
loop {
|
||||||
|
let exchange_ctr: ExchangeCtr<'_> = channel.recv().await;
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Handler {}: Got exchange {:?}",
|
||||||
|
handler_id,
|
||||||
|
exchange_ctr.id()
|
||||||
|
);
|
||||||
|
|
||||||
|
let result = self
|
||||||
|
.handle_exchange(tx_buf, rx_buf, sx_buf, exchange_ctr, handler)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Err(err) = result {
|
||||||
|
warn!(
|
||||||
|
"Handler {}: Exchange closed because of error: {:?}",
|
||||||
|
handler_id, err
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
info!("Handler {}: Exchange completed", handler_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[cfg_attr(feature = "nightly", allow(clippy::await_holding_refcell_ref))] // Fine because of the async mutex
|
||||||
|
pub async fn handle_exchange<H>(
|
||||||
|
&self,
|
||||||
|
tx_buf: &mut [u8; MAX_TX_BUF_SIZE],
|
||||||
|
rx_buf: &mut [u8; MAX_RX_BUF_SIZE],
|
||||||
|
sx_buf: &mut [u8; MAX_RX_STATUS_BUF_SIZE],
|
||||||
|
exchange_ctr: ExchangeCtr<'_>,
|
||||||
|
handler: &H,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
H: DataModelHandler,
|
||||||
|
{
|
||||||
|
let mut tx = alloc!(Packet::new_tx(tx_buf.as_mut()));
|
||||||
|
let mut rx = alloc!(Packet::new_rx(rx_buf.as_mut()));
|
||||||
|
|
||||||
|
let mut exchange = alloc!(exchange_ctr.get(&mut rx).await?);
|
||||||
|
|
||||||
|
match rx.get_proto_id() {
|
||||||
|
PROTO_ID_SECURE_CHANNEL => {
|
||||||
|
let sc = SecureChannel::new(self.matter());
|
||||||
|
|
||||||
|
sc.handle(&mut exchange, &mut rx, &mut tx).await?;
|
||||||
|
|
||||||
|
self.matter().notify_changed();
|
||||||
|
}
|
||||||
|
PROTO_ID_INTERACTION_MODEL => {
|
||||||
|
let dm = DataModel::new(handler);
|
||||||
|
|
||||||
|
let mut rx_status = alloc!(Packet::new_rx(sx_buf));
|
||||||
|
|
||||||
|
dm.handle(&mut exchange, &mut rx, &mut tx, &mut rx_status)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
self.matter().notify_changed();
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
error!("Unknown Proto-ID: {}", other);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_rx<'r>(
|
pub fn process_rx<'r>(
|
||||||
&'r self,
|
&'r self,
|
||||||
construction_notification: &'r Notification,
|
construction_notification: &'r Notification,
|
||||||
|
|
|
@ -17,26 +17,17 @@
|
||||||
|
|
||||||
use core::{mem::MaybeUninit, pin::pin};
|
use core::{mem::MaybeUninit, pin::pin};
|
||||||
|
|
||||||
use crate::{
|
|
||||||
alloc,
|
|
||||||
data_model::{core::DataModel, objects::DataModelHandler},
|
|
||||||
interaction_model::core::PROTO_ID_INTERACTION_MODEL,
|
|
||||||
CommissioningData, Matter,
|
|
||||||
};
|
|
||||||
use embassy_futures::select::{select, select_slice, Either};
|
use embassy_futures::select::{select, select_slice, Either};
|
||||||
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Channel};
|
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Channel};
|
||||||
use log::{error, info, warn};
|
|
||||||
|
|
||||||
use crate::{
|
use log::{error, info};
|
||||||
error::Error,
|
|
||||||
secure_channel::{common::PROTO_ID_SECURE_CHANNEL, core::SecureChannel},
|
use crate::{data_model::objects::DataModelHandler, CommissioningData, Matter};
|
||||||
transport::packet::{Packet, MAX_RX_BUF_SIZE},
|
use crate::{error::Error, transport::packet::MAX_RX_BUF_SIZE, utils::select::EitherUnwrap};
|
||||||
utils::select::EitherUnwrap,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
core::Transport,
|
core::Transport,
|
||||||
exchange::{ExchangeCtr, Notification, MAX_EXCHANGES},
|
exchange::{Notification, MAX_EXCHANGES},
|
||||||
packet::{MAX_RX_STATUS_BUF_SIZE, MAX_TX_BUF_SIZE},
|
packet::{MAX_RX_STATUS_BUF_SIZE, MAX_TX_BUF_SIZE},
|
||||||
pipe::{Chunk, Pipe},
|
pipe::{Chunk, Pipe},
|
||||||
};
|
};
|
||||||
|
@ -157,7 +148,7 @@ impl<'a> TransportRunner<'a> {
|
||||||
let mut mdns = pin!(mdns_runner.run_udp(stack, &mut buffers.mdns));
|
let mut mdns = pin!(mdns_runner.run_udp(stack, &mut buffers.mdns));
|
||||||
let mut transport = pin!(self.run_udp(stack, &mut buffers.transport, dev_comm, handler));
|
let mut transport = pin!(self.run_udp(stack, &mut buffers.transport, dev_comm, handler));
|
||||||
|
|
||||||
embassy_futures::select::select(&mut transport, &mut mdns)
|
embassy_futures::select::select(&mut mdns, &mut transport)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
@ -265,11 +256,12 @@ impl<'a> TransportRunner<'a> {
|
||||||
&construction_notification,
|
&construction_notification,
|
||||||
handler
|
handler
|
||||||
));
|
));
|
||||||
let mut tx = pin!(Self::handle_tx(&self.transport, tx_pipe));
|
let mut tx = pin!(self.transport.handle_tx(tx_pipe));
|
||||||
|
|
||||||
select(&mut rx, &mut tx).await.unwrap()
|
select(&mut rx, &mut tx).await.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
async fn handle_rx<H>(
|
async fn handle_rx<H>(
|
||||||
transport: &Transport<'_>,
|
transport: &Transport<'_>,
|
||||||
pools: &mut PacketPools,
|
pools: &mut PacketPools,
|
||||||
|
@ -289,85 +281,30 @@ impl<'a> TransportRunner<'a> {
|
||||||
|
|
||||||
info!("Handlers size: {}", core::mem::size_of_val(&handlers));
|
info!("Handlers size: {}", core::mem::size_of_val(&handlers));
|
||||||
|
|
||||||
let pools = &mut *pools as *mut _;
|
// Unsafely allow mutable aliasing in the packet pools by different indices
|
||||||
|
let pools: *mut PacketPools = pools;
|
||||||
|
|
||||||
for index in 0..MAX_EXCHANGES {
|
for index in 0..MAX_EXCHANGES {
|
||||||
let channel = &channel;
|
let channel = &channel;
|
||||||
let handler_id = index;
|
let handler_id = index;
|
||||||
|
|
||||||
|
let pools = unsafe { pools.as_mut() }.unwrap();
|
||||||
|
|
||||||
|
let tx_buf = unsafe { pools.tx[handler_id].assume_init_mut() };
|
||||||
|
let rx_buf = unsafe { pools.rx[handler_id].assume_init_mut() };
|
||||||
|
let sx_buf = unsafe { pools.sx[handler_id].assume_init_mut() };
|
||||||
|
|
||||||
handlers
|
handlers
|
||||||
.push(async move {
|
.push(
|
||||||
loop {
|
transport
|
||||||
let exchange_ctr: ExchangeCtr<'_> = channel.recv().await;
|
.exchange_handler(tx_buf, rx_buf, sx_buf, handler_id, channel, handler),
|
||||||
|
)
|
||||||
info!(
|
|
||||||
"Handler {}: Got exchange {:?}",
|
|
||||||
handler_id,
|
|
||||||
exchange_ctr.id()
|
|
||||||
);
|
|
||||||
|
|
||||||
let result = Self::handle_exchange(
|
|
||||||
transport,
|
|
||||||
pools,
|
|
||||||
handler_id,
|
|
||||||
exchange_ctr,
|
|
||||||
handler,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
|
|
||||||
if let Err(err) = result {
|
|
||||||
warn!(
|
|
||||||
"Handler {}: Exchange closed because of error: {:?}",
|
|
||||||
handler_id, err
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
info!("Handler {}: Exchange completed", handler_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.map_err(|_| ())
|
.map_err(|_| ())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rx = pin!(async {
|
let mut rx =
|
||||||
loop {
|
pin!(transport.handle_rx_multiplex(rx_pipe, &construction_notification, &channel));
|
||||||
info!("Transport: waiting for incoming packets");
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut data = rx_pipe.data.lock().await;
|
|
||||||
|
|
||||||
if let Some(chunk) = data.chunk {
|
|
||||||
let mut rx = alloc!(Packet::new_rx(&mut data.buf[chunk.start..chunk.end]));
|
|
||||||
rx.peer = chunk.addr;
|
|
||||||
|
|
||||||
if let Some(exchange_ctr) =
|
|
||||||
transport.process_rx(construction_notification, &mut rx)?
|
|
||||||
{
|
|
||||||
let exchange_id = exchange_ctr.id().clone();
|
|
||||||
|
|
||||||
info!("Transport: got new exchange: {:?}", exchange_id);
|
|
||||||
|
|
||||||
channel.send(exchange_ctr).await;
|
|
||||||
info!("Transport: exchange sent");
|
|
||||||
|
|
||||||
transport
|
|
||||||
.wait_construction(construction_notification, &rx, &exchange_id)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
info!("Transport: exchange started");
|
|
||||||
}
|
|
||||||
|
|
||||||
data.chunk = None;
|
|
||||||
rx_pipe.data_consumed_notification.signal(());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rx_pipe.data_supplied_notification.wait().await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unreachable_code)]
|
|
||||||
Ok::<_, Error>(())
|
|
||||||
});
|
|
||||||
|
|
||||||
let result = select(&mut rx, select_slice(&mut handlers)).await;
|
let result = select(&mut rx, select_slice(&mut handlers)).await;
|
||||||
|
|
||||||
|
@ -381,81 +318,4 @@ impl<'a> TransportRunner<'a> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_tx(transport: &Transport<'_>, tx_pipe: &Pipe<'_>) -> Result<(), Error> {
|
|
||||||
loop {
|
|
||||||
loop {
|
|
||||||
{
|
|
||||||
let mut data = tx_pipe.data.lock().await;
|
|
||||||
|
|
||||||
if data.chunk.is_none() {
|
|
||||||
let mut tx = alloc!(Packet::new_tx(data.buf));
|
|
||||||
|
|
||||||
if transport.pull_tx(&mut tx).await? {
|
|
||||||
data.chunk = Some(Chunk {
|
|
||||||
start: tx.get_writebuf()?.get_start(),
|
|
||||||
end: tx.get_writebuf()?.get_tail(),
|
|
||||||
addr: tx.peer,
|
|
||||||
});
|
|
||||||
tx_pipe.data_supplied_notification.signal(());
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tx_pipe.data_consumed_notification.wait().await;
|
|
||||||
}
|
|
||||||
|
|
||||||
transport.wait_tx().await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg_attr(feature = "nightly", allow(clippy::await_holding_refcell_ref))] // Fine because of the async mutex
|
|
||||||
async fn handle_exchange<H>(
|
|
||||||
transport: &Transport<'_>,
|
|
||||||
pools: *mut PacketPools,
|
|
||||||
handler_id: usize,
|
|
||||||
exchange_ctr: ExchangeCtr<'_>,
|
|
||||||
handler: &H,
|
|
||||||
) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
H: DataModelHandler,
|
|
||||||
{
|
|
||||||
let pools = unsafe { pools.as_mut() }.unwrap();
|
|
||||||
|
|
||||||
let tx_buf = unsafe { pools.tx[handler_id].assume_init_mut() };
|
|
||||||
let rx_buf = unsafe { pools.rx[handler_id].assume_init_mut() };
|
|
||||||
let rx_status_buf = unsafe { pools.sx[handler_id].assume_init_mut() };
|
|
||||||
|
|
||||||
let mut rx = alloc!(Packet::new_rx(rx_buf.as_mut()));
|
|
||||||
let mut tx = alloc!(Packet::new_tx(tx_buf.as_mut()));
|
|
||||||
|
|
||||||
let mut exchange = alloc!(exchange_ctr.get(&mut rx).await?);
|
|
||||||
|
|
||||||
match rx.get_proto_id() {
|
|
||||||
PROTO_ID_SECURE_CHANNEL => {
|
|
||||||
let sc = SecureChannel::new(transport.matter());
|
|
||||||
|
|
||||||
sc.handle(&mut exchange, &mut rx, &mut tx).await?;
|
|
||||||
|
|
||||||
transport.matter().notify_changed();
|
|
||||||
}
|
|
||||||
PROTO_ID_INTERACTION_MODEL => {
|
|
||||||
let dm = DataModel::new(handler);
|
|
||||||
|
|
||||||
let mut rx_status = alloc!(Packet::new_rx(rx_status_buf));
|
|
||||||
|
|
||||||
dm.handle(&mut exchange, &mut rx, &mut tx, &mut rx_status)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
transport.matter().notify_changed();
|
|
||||||
}
|
|
||||||
other => {
|
|
||||||
error!("Unknown Proto-ID: {}", other);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue