diff --git a/matter/src/interaction_model/core.rs b/matter/src/interaction_model/core.rs index dd77c78..adbda94 100644 --- a/matter/src/interaction_model/core.rs +++ b/matter/src/interaction_model/core.rs @@ -68,6 +68,16 @@ impl<'a> Transaction<'a> { } } + /// Terminates the transaction, no communication (even ACKs) happens hence forth + pub fn terminate(&mut self) { + self.state = TransactionState::Terminate + } + + pub fn is_terminate(&self) -> bool { + self.state == TransactionState::Terminate + } + + /// Marks the transaction as completed from the application's perspective pub fn complete(&mut self) { self.state = TransactionState::Complete } @@ -200,7 +210,9 @@ impl proto_demux::HandleProto for InteractionModel { info!("Sending response"); tlv::print_tlv_list(ctx.tx.as_borrow_slice()); } - if trans.is_complete() { + if trans.is_terminate() { + ctx.exch_ctx.exch.terminate(); + } else if trans.is_complete() { ctx.exch_ctx.exch.close(); } Ok(result) diff --git a/matter/src/interaction_model/mod.rs b/matter/src/interaction_model/mod.rs index c4d401b..98af4af 100644 --- a/matter/src/interaction_model/mod.rs +++ b/matter/src/interaction_model/mod.rs @@ -30,6 +30,7 @@ use self::{ pub enum TransactionState { Ongoing, Complete, + Terminate, } pub struct Transaction<'a> { pub state: TransactionState, diff --git a/matter/src/transport/exchange.rs b/matter/src/transport/exchange.rs index 2e67636..54f8a7a 100644 --- a/matter/src/transport/exchange.rs +++ b/matter/src/transport/exchange.rs @@ -48,10 +48,15 @@ impl Default for Role { } } +/// State of the exchange #[derive(Debug, PartialEq)] enum State { + /// The exchange is open and active Open, + /// The exchange is closed, but keys are active since retransmissions/acks may be pending Close, + /// The exchange is terminated, keys are destroyed, no communication can happen + Terminate, } impl Default for State { @@ -100,6 +105,11 @@ impl Exchange { } } + pub fn terminate(&mut self) { + self.data = DataOption::None; + self.state = State::Terminate; + } + pub fn close(&mut self) { self.data = DataOption::None; self.state = State::Close; @@ -111,7 +121,7 @@ impl Exchange { pub fn is_purgeable(&self) -> bool { // No Users, No pending ACKs/Retrans - self.state == State::Close && self.mrp.is_empty() + self.state == State::Terminate || (self.state == State::Close && self.mrp.is_empty()) } pub fn get_id(&self) -> u16 { @@ -170,6 +180,11 @@ impl Exchange { mut proto_tx: BoxSlab, session: &mut SessionHandle, ) -> Result<(), Error> { + if self.state == State::Terminate { + info!("Skipping tx for terminated exchange {}", self.id); + return Ok(()); + } + trace!("payload: {:x?}", proto_tx.as_borrow_slice()); info!( "{} with proto id: {} opcode: {}",