umsh_node_mgmt/
lib.rs

1#![cfg_attr(not(test), no_std)]
2
3//! The Node Management binding: ULCP over the mesh.
4//!
5//! A node that supports node management is configured and observed over
6//! the mesh itself, in the same command grammar and property model
7//! [`umsh_ulcp`] defines for the local link. **Node Management Request**
8//! (payload type 8) and **Node Management Response** (payload type 9)
9//! payloads carry ordinary ULCP frames between an **administrator** — a
10//! node listed in the device's `PROP_DEV_ADMINS` — and the **device**.
11//! `docs/protocol/src/app-node-management.md` specifies it.
12//!
13//! The binding relies on exactly what secure unicast guarantees — an
14//! authenticated source, confidentiality, and replay protection — and
15//! adds what the ULCP grammar needs on a transport that promises neither
16//! delivery nor ordering:
17//!
18//! - a [token](envelope::Token) correlating a response with its request,
19//!   in place of the TID of the local bindings;
20//! - [retained responses](device::DeviceEngine), so a retransmission is
21//!   answered again rather than executed again;
22//! - [cursors](device::DeviceEngine::begin), carrying a read larger than
23//!   one frame across as many exchanges as it takes, with no per-read
24//!   state on the device.
25//!
26//! Both engines are sans-IO: they own no transport, no clock, and no
27//! buffers beyond their own state. The caller sends the payloads they
28//! hand out, feeds back the ones that arrive, and supplies the time.
29//! Authorization is likewise the caller's: a request reaches
30//! [`device::DeviceEngine`] only after its source has been checked
31//! against the administrator list.
32
33#[cfg(feature = "alloc")]
34extern crate alloc;
35
36pub mod admin;
37pub mod device;
38pub mod envelope;
39pub mod fragment;
40#[cfg(feature = "node")]
41pub mod node_adapter;
42
43pub use admin::{Exchange, Failure, Outcome, Reassembly, Step};
44pub use device::{DeviceEngine, Dispatch, DropReason, Ingress, Produced, PublicKey};
45pub use envelope::{Envelope, EnvelopeError, Token};
46pub use fragment::{continuable, produce, trailing, trailing_offset};
47#[cfg(feature = "node")]
48pub use node_adapter::{BeginError, ManagementError, NodeManager, Progress};
49
50/// The Node Management payload an administrator sizes its requests
51/// against.
52///
53/// A device derives its own ceiling from the radio it has — see
54/// `ADMIN_PAYLOAD_MAX` in `umsh-ulcp-runtime` — and it is the device's
55/// number that actually bounds an exchange. An administrator cannot ask
56/// what that number is, so it assumes the smallest a device is allowed
57/// to have, and the device's derivation is checked against this one at
58/// compile time.
59pub const PAYLOAD_MAX: usize = 180;
60
61/// The largest request frame that fits a payload once its envelope is
62/// accounted for.
63pub const REQUEST_MAX: usize = PAYLOAD_MAX - envelope::OVERHEAD_MAX;