Skip to content

Commit 916f214

Browse files
committed
Simplify API by combining Matter, Transport and TransportRunner; simplify Mdns and Psm runners
1 parent 71b9a57 commit 916f214

File tree

29 files changed

+519
-628
lines changed

29 files changed

+519
-628
lines changed

.github/workflows/test-linux.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ jobs:
1515
runs-on: ubuntu-latest
1616
strategy:
1717
matrix:
18-
crypto-backend: ['crypto_openssl', 'crypto_rustcrypto', 'crypto_mbedtls']
18+
crypto-backend: ['rustcrypto', 'mbedtls', 'openssl']
1919

2020
steps:
2121
- uses: actions/checkout@v2
2222
- name: Build
23-
run: cd matter; cargo build --verbose --no-default-features --features ${{matrix.crypto-backend}}
23+
run: cd matter; cargo build --no-default-features --features ${{matrix.crypto-backend}}
2424
- name: Run tests
25-
run: cd matter; cargo test --verbose --no-default-features --features ${{matrix.crypto-backend}} -- --test-threads=1
25+
run: cd matter; cargo test --no-default-features --features os,${{matrix.crypto-backend}} -- --test-threads=1

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
[workspace]
2+
resolver = "2"
23
members = ["matter", "matter_macro_derive"]
34

4-
exclude = ["examples/*"]
5+
exclude = ["examples/*", "tools/tlv_tool"]
56

67
# For compatibility with ESP IDF
78
[patch.crates-io]

README.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,23 +41,24 @@ The `async` metaphor however comes with a bit higher memory usage, due to not en
4141

4242
## Build
4343

44-
Building the library:
44+
### Building the library
4545

4646
```
4747
$ cargo build
4848
```
4949

50-
Building and running the example (Linux, MacOS X):
50+
### Building and running the example (Linux, MacOS X)
5151

5252
```
5353
$ cargo run --example onoff_light
5454
```
5555

56-
Building the example (Espressif's ESP-IDF):
56+
### Building the example (Espressif's ESP-IDF)
57+
5758
* Install all build prerequisites described [here](https://github.com/esp-rs/esp-idf-template#prerequisites)
5859
* Build with the following command line:
5960
```
60-
export MCU=esp32; export CARGO_TARGET_XTENSA_ESP32_ESPIDF_LINKER=ldproxy; export RUSTFLAGS="-C default-linker-libraries"; export WIFI_SSID=ssid;export WIFI_PASS=pass; cargo build --example onoff_light --no-default-features --features std,crypto_rustcrypto --target xtensa-esp32-espidf -Zbuild-std=std,panic_abort
61+
export MCU=esp32; export CARGO_TARGET_XTENSA_ESP32_ESPIDF_LINKER=ldproxy; export RUSTFLAGS="-C default-linker-libraries"; export WIFI_SSID=ssid;export WIFI_PASS=pass; cargo build --example onoff_light --no-default-features --features esp-idf --target xtensa-esp32-espidf -Zbuild-std=std,panic_abort
6162
```
6263
* If you are building for a different Espressif MCU, change the `MCU` variable, the `xtensa-esp32-espidf` target and the name of the `CARGO_TARGET_<esp-idf-target-uppercase>_LINKER` variable to match your MCU and its Rust target. Available Espressif MCUs and targets are:
6364
* esp32 / xtensa-esp32-espidf
@@ -69,6 +70,10 @@ export MCU=esp32; export CARGO_TARGET_XTENSA_ESP32_ESPIDF_LINKER=ldproxy; export
6970
* Put in `WIFI_SSID` / `WIFI_PASS` the SSID & password for your wireless router
7071
* Flash using the `espflash` utility described in the build prerequsites' link above
7172

73+
### Building the example (ESP32-XX baremetal or RP2040)
74+
75+
Coming soon!
76+
7277
## Test
7378

7479
With the `chip-tool` (the current tool for testing Matter) use the Ethernet commissioning mechanism:

examples/onoff_light/src/main.rs

Lines changed: 40 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use core::borrow::Borrow;
1919
use core::pin::pin;
2020

21+
use embassy_futures::select::select3;
2122
use log::info;
2223
use matter::core::{CommissioningData, Matter};
2324
use matter::data_model::cluster_basic_information::BasicInfoConfig;
@@ -27,18 +28,18 @@ use matter::data_model::objects::*;
2728
use matter::data_model::root_endpoint;
2829
use matter::data_model::system_model::descriptor;
2930
use matter::error::Error;
30-
use matter::mdns::MdnsService;
31-
use matter::persist::FilePsm;
31+
use matter::mdns::{MdnsRunBuffers, MdnsService};
3232
use matter::secure_channel::spake2p::VerifierData;
33+
use matter::transport::core::RunBuffers;
3334
use matter::transport::network::{Ipv4Addr, Ipv6Addr, NetworkStack};
34-
use matter::transport::runner::{AllUdpBuffers, TransportRunner};
35+
use matter::utils::select::EitherUnwrap;
3536

3637
mod dev_att;
3738

3839
#[cfg(feature = "std")]
3940
fn main() -> Result<(), Error> {
4041
let thread = std::thread::Builder::new()
41-
.stack_size(140 * 1024)
42+
.stack_size(150 * 1024)
4243
.spawn(run)
4344
.unwrap();
4445

@@ -56,11 +57,11 @@ fn run() -> Result<(), Error> {
5657
initialize_logger();
5758

5859
info!(
59-
"Matter memory: mDNS={}, Matter={}, TransportRunner={}, UdpBuffers={}",
60+
"Matter memory: mDNS={}, Matter={}, MdnsBuffers={}, RunBuffers={}",
6061
core::mem::size_of::<MdnsService>(),
6162
core::mem::size_of::<Matter>(),
62-
core::mem::size_of::<TransportRunner>(),
63-
core::mem::size_of::<AllUdpBuffers>(),
63+
core::mem::size_of::<MdnsRunBuffers>(),
64+
core::mem::size_of::<RunBuffers>(),
6465
);
6566

6667
let dev_det = BasicInfoConfig {
@@ -73,12 +74,6 @@ fn run() -> Result<(), Error> {
7374
device_name: "OnOff Light",
7475
};
7576

76-
let psm_path = std::env::temp_dir().join("matter-iot");
77-
info!("Persisting from/to {}", psm_path.display());
78-
79-
#[cfg(all(feature = "std", not(target_os = "espidf")))]
80-
let psm = matter::persist::FilePsm::new(psm_path)?;
81-
8277
let (ipv4_addr, ipv6_addr, interface) = initialize_network()?;
8378

8479
let dev_att = dev_att::HardCodedDevAtt::new();
@@ -106,7 +101,7 @@ fn run() -> Result<(), Error> {
106101
matter::MATTER_PORT,
107102
);
108103

109-
info!("mDNS initialized: {:p}", &mdns);
104+
info!("mDNS initialized");
110105

111106
let matter = Matter::new(
112107
// vid/pid should match those in the DAC
@@ -118,53 +113,59 @@ fn run() -> Result<(), Error> {
118113
matter::MATTER_PORT,
119114
);
120115

121-
info!("Matter initialized: {:p}", &matter);
116+
info!("Matter initialized");
122117

123118
#[cfg(all(feature = "std", not(target_os = "espidf")))]
124-
{
125-
let mut buf = [0; 4096];
126-
let buf = &mut buf;
127-
if let Some(data) = psm.load("acls", buf)? {
128-
matter.load_acls(data)?;
129-
}
130-
131-
if let Some(data) = psm.load("fabrics", buf)? {
132-
matter.load_fabrics(data)?;
133-
}
134-
}
135-
136-
let mut runner = TransportRunner::new(&matter);
137-
138-
info!("Transport runner initialized: {:p}", &runner);
119+
let mut psm = matter::persist::Psm::new(&matter, std::env::temp_dir().join("matter-iot"))?;
139120

140121
let handler = HandlerCompat(handler(&matter));
141122

142-
// NOTE (no_std): If using the `embassy-net` UDP implementation, replace this dummy stack with the `embassy-net` one
143-
// When using a custom UDP stack, remove this
123+
// When using a custom UDP stack, remove the network stack initialization below
124+
// and call `Matter::run_piped()` instead, by utilizing the TX & RX `Pipe` structs
125+
// to push/pull your UDP packets from/to the Matter stack.
126+
// Ditto for `MdnsService`.
127+
//
128+
// When using the `embassy-net` feature (as opposed to the Rust Standard Library network stack),
129+
// this initialization would be more complex.
144130
let stack = NetworkStack::new();
145131

146-
let mut buffers = AllUdpBuffers::new();
132+
let mut mdns_buffers = MdnsRunBuffers::new();
133+
let mut mdns_runner = pin!(mdns.run(&stack, &mut mdns_buffers));
147134

148-
let mut fut = pin!(runner.run_udp_all(
135+
let mut buffers = RunBuffers::new();
136+
let mut runner = matter.run(
149137
&stack,
150-
&mdns,
151138
&mut buffers,
152139
CommissioningData {
153140
// TODO: Hard-coded for now
154141
verifier: VerifierData::new_with_pw(123456, *matter.borrow()),
155142
discriminator: 250,
156143
},
157144
&handler,
158-
));
145+
);
146+
147+
info!(
148+
"Matter transport runner memory: {}",
149+
core::mem::size_of_val(&runner)
150+
);
151+
152+
let mut runner = pin!(runner);
153+
154+
#[cfg(all(feature = "std", not(target_os = "espidf")))]
155+
let mut psm_runner = pin!(psm.run());
156+
157+
#[cfg(not(all(feature = "std", not(target_os = "espidf"))))]
158+
let mut psm_runner = pin!(core::future::pending());
159+
160+
let mut runner = select3(&mut runner, &mut mdns_runner, &mut psm_runner);
159161

160-
// NOTE: For no_std, replace with your own no_std way of polling the future
161162
#[cfg(feature = "std")]
162-
async_io::block_on(&mut fut)?;
163+
async_io::block_on(&mut runner).unwrap()?;
163164

164165
// NOTE (no_std): For no_std, replace with your own more efficient no_std executor,
165166
// because the executor used below is a simple busy-loop poller
166167
#[cfg(not(feature = "std"))]
167-
embassy_futures::block_on(&mut fut)?;
168+
embassy_futures::block_on(&mut runner).unwrap()?;
168169

169170
Ok(())
170171
}
@@ -268,26 +269,6 @@ fn initialize_network() -> Result<(Ipv4Addr, Ipv6Addr, u32), Error> {
268269
Ok((ip, ipv6, 0 as _))
269270
}
270271

271-
#[cfg(all(feature = "std", not(target_os = "espidf")))]
272-
#[inline(never)]
273-
async fn save(matter: &Matter<'_>, psm: &FilePsm) -> Result<(), Error> {
274-
let mut buf = [0; 4096];
275-
let buf = &mut buf;
276-
277-
loop {
278-
matter.wait_changed().await;
279-
if matter.is_changed() {
280-
if let Some(data) = matter.store_acls(buf)? {
281-
psm.store("acls", data)?;
282-
}
283-
284-
if let Some(data) = matter.store_fabrics(buf)? {
285-
psm.store("fabrics", data)?;
286-
}
287-
}
288-
}
289-
}
290-
291272
#[cfg(target_os = "espidf")]
292273
#[inline(never)]
293274
fn initialize_logger() {

matter/Cargo.toml

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,23 @@ repository = "https://github.com/kedars/matter-rs"
88
readme = "README.md"
99
keywords = ["matter", "smart", "smart-home", "IoT", "ESP32"]
1010
categories = ["embedded", "network-programming"]
11-
license = "MIT"
11+
license = "Apache-2.0"
1212

1313
[lib]
1414
name = "matter"
1515
path = "src/lib.rs"
1616

1717
[features]
18-
default = ["os", "crypto_rustcrypto"]
18+
default = ["os", "mbedtls"]
1919
os = ["std", "backtrace", "env_logger", "nix", "critical-section/std", "embassy-sync/std", "embassy-time/std"]
20-
esp-idf = ["std", "crypto_rustcrypto", "esp-idf-sys", "esp-idf-hal", "esp-idf-svc"]
20+
esp-idf = ["std", "rustcrypto", "esp-idf-sys"]
2121
std = ["alloc", "rand", "qrcode", "async-io", "esp-idf-sys?/std", "embassy-time/generic-queue-16"]
2222
backtrace = []
2323
alloc = []
2424
nightly = []
25-
crypto_openssl = ["alloc", "openssl", "foreign-types", "hmac", "sha2"]
26-
crypto_mbedtls = ["alloc", "mbedtls"]
27-
crypto_rustcrypto = ["alloc", "sha2", "hmac", "pbkdf2", "hkdf", "aes", "ccm", "p256", "elliptic-curve", "crypto-bigint", "x509-cert", "rand_core"]
25+
openssl = ["alloc", "dep:openssl", "foreign-types", "hmac", "sha2"]
26+
mbedtls = ["alloc", "dep:mbedtls"]
27+
rustcrypto = ["alloc", "sha2", "hmac", "pbkdf2", "hkdf", "aes", "ccm", "p256", "elliptic-curve", "crypto-bigint", "x509-cert", "rand_core"]
2828
embassy-net = ["dep:embassy-net", "dep:embassy-net-driver", "smoltcp"]
2929

3030
[dependencies]
@@ -58,10 +58,10 @@ smoltcp = { version = "0.10", default-features = false, optional = true }
5858
# STD-only dependencies
5959
rand = { version = "0.8.5", optional = true }
6060
qrcode = { version = "0.12", default-features = false, optional = true } # Print QR code
61-
async-io = { version = "=1.12", optional = true } # =1.2 for compatibility with ESP IDF
61+
async-io = { version = "=1.12", optional = true } # =1.12 for compatibility with ESP IDF
6262

6363
# crypto
64-
openssl = { git = "https://github.com/sfackler/rust-openssl", optional = true }
64+
openssl = { version = "0.10.55", optional = true }
6565
foreign-types = { version = "0.3.2", optional = true }
6666

6767
# rust-crypto
@@ -81,18 +81,22 @@ x509-cert = { version = "0.2.0", default-features = false, features = ["pem"], o
8181
astro-dnssd = { version = "0.3" }
8282

8383
[target.'cfg(not(target_os = "espidf"))'.dependencies]
84-
mbedtls = { git = "https://github.com/fortanix/rust-mbedtls", optional = true }
84+
mbedtls = { version = "0.9", optional = true }
8585
env_logger = { version = "0.10.0", optional = true }
8686
nix = { version = "0.26", features = ["net"], optional = true }
8787

8888
[target.'cfg(target_os = "espidf")'.dependencies]
89-
esp-idf-sys = { version = "0.33", optional = true, default-features = false, features = ["native", "binstart"] }
90-
esp-idf-hal = { version = "0.41", optional = true, features = ["embassy-sync", "critical-section"] } # TODO: Only necessary for the examples
91-
esp-idf-svc = { version = "0.46", optional = true, features = ["embassy-time-driver"] } # TODO: Only necessary for the examples
89+
esp-idf-sys = { version = "0.33", optional = true, default-features = false, features = ["native"] }
9290

9391
[build-dependencies]
9492
embuild = "0.31.2"
9593

94+
[target.'cfg(target_os = "espidf")'.dev-dependencies]
95+
esp-idf-sys = { version = "0.33", default-features = false, features = ["binstart"] }
96+
esp-idf-hal = { version = "0.41", features = ["embassy-sync", "critical-section"] }
97+
esp-idf-svc = { version = "0.46", features = ["embassy-time-driver"] }
98+
embedded-svc = { version = "0.25" }
99+
96100
[[example]]
97101
name = "onoff_light"
98102
path = "../examples/onoff_light/src/main.rs"

matter/src/core.rs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ use crate::{
2828
mdns::Mdns,
2929
pairing::{print_pairing_code_and_qr, DiscoveryCapabilities},
3030
secure_channel::{pake::PaseMgr, spake2p::VerifierData},
31-
transport::exchange::Notification,
32-
utils::{epoch::Epoch, rand::Rand},
31+
transport::{
32+
exchange::{ExchangeCtx, MAX_EXCHANGES},
33+
session::SessionMgr,
34+
},
35+
utils::{epoch::Epoch, rand::Rand, select::Notification},
3336
};
3437

3538
/* The Matter Port */
@@ -45,17 +48,20 @@ pub struct CommissioningData {
4548

4649
/// The primary Matter Object
4750
pub struct Matter<'a> {
48-
pub fabric_mgr: RefCell<FabricMgr>,
49-
pub acl_mgr: RefCell<AclMgr>,
50-
pub pase_mgr: RefCell<PaseMgr>,
51-
pub failsafe: RefCell<FailSafe>,
52-
pub persist_notification: Notification,
53-
pub mdns: &'a dyn Mdns,
54-
pub epoch: Epoch,
55-
pub rand: Rand,
56-
pub dev_det: &'a BasicInfoConfig<'a>,
57-
pub dev_att: &'a dyn DevAttDataFetcher,
58-
pub port: u16,
51+
fabric_mgr: RefCell<FabricMgr>,
52+
pub acl_mgr: RefCell<AclMgr>, // Public for tests
53+
pase_mgr: RefCell<PaseMgr>,
54+
failsafe: RefCell<FailSafe>,
55+
persist_notification: Notification,
56+
pub(crate) send_notification: Notification,
57+
mdns: &'a dyn Mdns,
58+
pub(crate) epoch: Epoch,
59+
pub(crate) rand: Rand,
60+
dev_det: &'a BasicInfoConfig<'a>,
61+
dev_att: &'a dyn DevAttDataFetcher,
62+
pub(crate) port: u16,
63+
pub(crate) exchanges: RefCell<heapless::Vec<ExchangeCtx, MAX_EXCHANGES>>,
64+
pub session_mgr: RefCell<SessionMgr>, // Public for tests
5965
}
6066

6167
impl<'a> Matter<'a> {
@@ -94,12 +100,15 @@ impl<'a> Matter<'a> {
94100
pase_mgr: RefCell::new(PaseMgr::new(epoch, rand)),
95101
failsafe: RefCell::new(FailSafe::new()),
96102
persist_notification: Notification::new(),
103+
send_notification: Notification::new(),
97104
mdns,
98105
epoch,
99106
rand,
100107
dev_det,
101108
dev_att,
102109
port,
110+
exchanges: RefCell::new(heapless::Vec::new()),
111+
session_mgr: RefCell::new(SessionMgr::new(epoch, rand)),
103112
}
104113
}
105114

@@ -160,6 +169,7 @@ impl<'a> Matter<'a> {
160169
Ok(false)
161170
}
162171
}
172+
163173
pub fn notify_changed(&self) {
164174
if self.is_changed() {
165175
self.persist_notification.signal(());

0 commit comments

Comments
 (0)