Skip to main content

rs_matter/sc/
busy.rs

1/*
2 *
3 *    Copyright (c) 2024-2026 Project CHIP Authors
4 *
5 *    Licensed under the Apache License, Version 2.0 (the "License");
6 *    you may not use this file except in compliance with the License.
7 *    You may obtain a copy of the License at
8 *
9 *        http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *    Unless required by applicable law or agreed to in writing, software
12 *    distributed under the License is distributed on an "AS IS" BASIS,
13 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *    See the License for the specific language governing permissions and
15 *    limitations under the License.
16 */
17
18use core::future::Future;
19
20use crate::error::*;
21use crate::respond::ExchangeHandler;
22use crate::transport::exchange::Exchange;
23
24use super::{sc_write, OpCode, SCStatusCodes, PROTO_ID_SECURE_CHANNEL};
25
26/// A Secure Channel implementation that is only capable of sending Busy status codes
27///
28/// Use with e.g.
29///
30/// ```ignore
31/// let matter = Matter::new(...);
32///
33/// // ...
34///
35/// let busy_responder = Responder::new("SC Busy Responder", BusySecureChannel::new(), &matter, 200/*ms*/);
36/// busy_responder.run::<10>().await?;
37/// ```
38///
39/// ... to respond with "I'm busy, please try later" status code to all incoming Secure Channel messages, which were
40/// not accepted in time by the actual Secure Channel responder, due to all its handlers being occupied with work.
41pub struct BusySecureChannel(());
42
43impl Default for BusySecureChannel {
44    fn default() -> Self {
45        Self::new()
46    }
47}
48
49impl BusySecureChannel {
50    const BUSY_RETRY_DELAY_MS: u16 = 500;
51
52    #[inline(always)]
53    pub const fn new() -> Self {
54        Self(())
55    }
56
57    pub async fn handle(&self, mut exchange: Exchange<'_>) -> Result<(), Error> {
58        let meta = exchange.recv().await?.meta();
59        if meta.proto_id != PROTO_ID_SECURE_CHANNEL {
60            Err(ErrorCode::InvalidProto)?;
61        }
62
63        match meta.opcode()? {
64            OpCode::PBKDFParamRequest | OpCode::CASESigma1 => {
65                exchange
66                    .send_with(|_, wb| {
67                        sc_write(
68                            wb,
69                            SCStatusCodes::Busy,
70                            &u16::to_le_bytes(Self::BUSY_RETRY_DELAY_MS),
71                        )
72                    })
73                    .await
74            }
75            proto_opcode => {
76                error!("OpCode not handled: {:?}", proto_opcode);
77                Err(ErrorCode::InvalidOpcode.into())
78            }
79        }
80    }
81}
82
83impl ExchangeHandler for BusySecureChannel {
84    fn handle(&self, exchange: Exchange<'_>) -> impl Future<Output = Result<(), Error>> {
85        BusySecureChannel::handle(self, exchange)
86    }
87}