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 crate::{error::ErrorCode, secure_channel::common::OpCode, Matter};
 | 
			
		||||
use embassy_futures::select::select;
 | 
			
		||||
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Channel};
 | 
			
		||||
use embassy_time::{Duration, Timer};
 | 
			
		||||
use log::info;
 | 
			
		||||
 | 
			
		||||
use log::{error, info, warn};
 | 
			
		||||
 | 
			
		||||
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::{
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +42,8 @@ use super::{
 | 
			
		|||
        MAX_EXCHANGES,
 | 
			
		||||
    },
 | 
			
		||||
    mrp::ReliableMessage,
 | 
			
		||||
    packet::{MAX_RX_BUF_SIZE, MAX_RX_STATUS_BUF_SIZE, MAX_TX_BUF_SIZE},
 | 
			
		||||
    pipe::{Chunk, Pipe},
 | 
			
		||||
    session::SessionMgr,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,6 +95,165 @@ impl<'a> Transport<'a> {
 | 
			
		|||
        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>(
 | 
			
		||||
        &'r self,
 | 
			
		||||
        construction_notification: &'r Notification,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,26 +17,17 @@
 | 
			
		|||
 | 
			
		||||
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_sync::{blocking_mutex::raw::NoopRawMutex, channel::Channel};
 | 
			
		||||
use log::{error, info, warn};
 | 
			
		||||
 | 
			
		||||
use crate::{
 | 
			
		||||
    error::Error,
 | 
			
		||||
    secure_channel::{common::PROTO_ID_SECURE_CHANNEL, core::SecureChannel},
 | 
			
		||||
    transport::packet::{Packet, MAX_RX_BUF_SIZE},
 | 
			
		||||
    utils::select::EitherUnwrap,
 | 
			
		||||
};
 | 
			
		||||
use log::{error, info};
 | 
			
		||||
 | 
			
		||||
use crate::{data_model::objects::DataModelHandler, CommissioningData, Matter};
 | 
			
		||||
use crate::{error::Error, transport::packet::MAX_RX_BUF_SIZE, utils::select::EitherUnwrap};
 | 
			
		||||
 | 
			
		||||
use super::{
 | 
			
		||||
    core::Transport,
 | 
			
		||||
    exchange::{ExchangeCtr, Notification, MAX_EXCHANGES},
 | 
			
		||||
    exchange::{Notification, MAX_EXCHANGES},
 | 
			
		||||
    packet::{MAX_RX_STATUS_BUF_SIZE, MAX_TX_BUF_SIZE},
 | 
			
		||||
    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 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
 | 
			
		||||
            .unwrap()
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -265,11 +256,12 @@ impl<'a> TransportRunner<'a> {
 | 
			
		|||
            &construction_notification,
 | 
			
		||||
            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()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[inline(always)]
 | 
			
		||||
    async fn handle_rx<H>(
 | 
			
		||||
        transport: &Transport<'_>,
 | 
			
		||||
        pools: &mut PacketPools,
 | 
			
		||||
| 
						 | 
				
			
			@ -289,85 +281,30 @@ impl<'a> TransportRunner<'a> {
 | 
			
		|||
 | 
			
		||||
        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 {
 | 
			
		||||
            let channel = &channel;
 | 
			
		||||
            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
 | 
			
		||||
                .push(async move {
 | 
			
		||||
                    loop {
 | 
			
		||||
                        let exchange_ctr: ExchangeCtr<'_> = channel.recv().await;
 | 
			
		||||
 | 
			
		||||
                        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);
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
                .push(
 | 
			
		||||
                    transport
 | 
			
		||||
                        .exchange_handler(tx_buf, rx_buf, sx_buf, handler_id, channel, handler),
 | 
			
		||||
                )
 | 
			
		||||
                .map_err(|_| ())
 | 
			
		||||
                .unwrap();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let mut rx = pin!(async {
 | 
			
		||||
            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) =
 | 
			
		||||
                            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 mut rx =
 | 
			
		||||
            pin!(transport.handle_rx_multiplex(rx_pipe, &construction_notification, &channel));
 | 
			
		||||
 | 
			
		||||
        let result = select(&mut rx, select_slice(&mut handlers)).await;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -381,81 +318,4 @@ impl<'a> TransportRunner<'a> {
 | 
			
		|||
 | 
			
		||||
        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