umsh_node/
mac.rs

1use umsh_core::{ChannelId, ChannelKey, PublicKey};
2use umsh_mac::{
3    CapacityError, LocalIdentityId, MacHandle, PeerId, Platform, SendError, SendOptions,
4    SendReceipt,
5};
6
7/// Pluggable backend that the node layer delegates to for MAC operations.
8///
9/// [`MacHandle`](umsh_mac::MacHandle) implements `MacBackend`, and test code can provide a
10/// lightweight fake.
11pub trait MacBackend: Clone {
12    /// Error type returned by send-oriented operations.
13    type SendError;
14    /// Error type returned by fixed-capacity operations.
15    type CapacityError;
16
17    /// Add or refresh a peer.
18    async fn add_peer(
19        &self,
20        key: PublicKey,
21    ) -> Result<PeerId, MacBackendError<Self::SendError, Self::CapacityError>>;
22    /// Add or refresh a private channel.
23    async fn add_private_channel(
24        &self,
25        key: ChannelKey,
26    ) -> Result<(), MacBackendError<Self::SendError, Self::CapacityError>>;
27    /// Add or refresh a named channel.
28    async fn add_named_channel(
29        &self,
30        name: &str,
31    ) -> Result<(), MacBackendError<Self::SendError, Self::CapacityError>>;
32    /// Queue a broadcast frame.
33    async fn send_broadcast(
34        &self,
35        from: LocalIdentityId,
36        payload: &[u8],
37        options: &SendOptions,
38    ) -> Result<SendReceipt, MacBackendError<Self::SendError, Self::CapacityError>>;
39    /// Queue a multicast frame.
40    async fn send_multicast(
41        &self,
42        from: LocalIdentityId,
43        channel: &ChannelId,
44        payload: &[u8],
45        options: &SendOptions,
46    ) -> Result<SendReceipt, MacBackendError<Self::SendError, Self::CapacityError>>;
47    /// Queue a unicast frame.
48    async fn send_unicast(
49        &self,
50        from: LocalIdentityId,
51        dst: &PublicKey,
52        payload: &[u8],
53        options: &SendOptions,
54    ) -> Result<Option<SendReceipt>, MacBackendError<Self::SendError, Self::CapacityError>>;
55    /// Queue a blind-unicast frame.
56    async fn send_blind_unicast(
57        &self,
58        from: LocalIdentityId,
59        dst: &PublicKey,
60        channel: &ChannelId,
61        payload: &[u8],
62        options: &SendOptions,
63    ) -> Result<Option<SendReceipt>, MacBackendError<Self::SendError, Self::CapacityError>>;
64    /// Fill `dest` with random bytes.
65    async fn fill_random(&self, dest: &mut [u8]);
66    /// Return the current MAC clock time.
67    async fn now_ms(&self) -> u64;
68
69    #[cfg(feature = "software-crypto")]
70    async fn register_ephemeral(
71        &self,
72        parent: LocalIdentityId,
73        identity: umsh_crypto::software::SoftwareIdentity,
74    ) -> Result<LocalIdentityId, MacBackendError<Self::SendError, Self::CapacityError>>;
75
76    #[cfg(feature = "software-crypto")]
77    async fn remove_ephemeral(&self, id: LocalIdentityId) -> bool;
78}
79
80/// Normalized wrapper around MAC-backend failures.
81#[derive(Clone, Debug, PartialEq, Eq)]
82pub enum MacBackendError<S, C> {
83    /// Send-oriented MAC failure.
84    Send(S),
85    /// Capacity-related MAC failure.
86    Capacity(C),
87}
88
89impl<
90    'a,
91    P: Platform,
92    const IDENTITIES: usize,
93    const PEERS: usize,
94    const CHANNELS: usize,
95    const ACKS: usize,
96    const TX: usize,
97    const FRAME: usize,
98    const DUP: usize,
99> MacBackend for MacHandle<'a, P, IDENTITIES, PEERS, CHANNELS, ACKS, TX, FRAME, DUP>
100{
101    type SendError = SendError;
102    type CapacityError = CapacityError;
103
104    async fn add_peer(
105        &self,
106        key: PublicKey,
107    ) -> Result<PeerId, MacBackendError<Self::SendError, Self::CapacityError>> {
108        self.add_peer(key).await.map_err(MacBackendError::Capacity)
109    }
110
111    async fn add_private_channel(
112        &self,
113        key: ChannelKey,
114    ) -> Result<(), MacBackendError<Self::SendError, Self::CapacityError>> {
115        self.add_channel(key)
116            .await
117            .map_err(MacBackendError::Capacity)
118    }
119
120    async fn add_named_channel(
121        &self,
122        name: &str,
123    ) -> Result<(), MacBackendError<Self::SendError, Self::CapacityError>> {
124        self.add_named_channel(name)
125            .await
126            .map_err(MacBackendError::Capacity)
127    }
128
129    async fn send_broadcast(
130        &self,
131        from: LocalIdentityId,
132        payload: &[u8],
133        options: &SendOptions,
134    ) -> Result<SendReceipt, MacBackendError<Self::SendError, Self::CapacityError>> {
135        self.send_broadcast(from, payload, options)
136            .await
137            .map_err(MacBackendError::Send)
138    }
139
140    async fn send_multicast(
141        &self,
142        from: LocalIdentityId,
143        channel: &ChannelId,
144        payload: &[u8],
145        options: &SendOptions,
146    ) -> Result<SendReceipt, MacBackendError<Self::SendError, Self::CapacityError>> {
147        self.send_multicast(from, channel, payload, options)
148            .await
149            .map_err(MacBackendError::Send)
150    }
151
152    async fn send_unicast(
153        &self,
154        from: LocalIdentityId,
155        dst: &PublicKey,
156        payload: &[u8],
157        options: &SendOptions,
158    ) -> Result<Option<SendReceipt>, MacBackendError<Self::SendError, Self::CapacityError>> {
159        self.send_unicast(from, dst, payload, options)
160            .await
161            .map_err(MacBackendError::Send)
162    }
163
164    async fn send_blind_unicast(
165        &self,
166        from: LocalIdentityId,
167        dst: &PublicKey,
168        channel: &ChannelId,
169        payload: &[u8],
170        options: &SendOptions,
171    ) -> Result<Option<SendReceipt>, MacBackendError<Self::SendError, Self::CapacityError>> {
172        self.send_blind_unicast(from, dst, channel, payload, options)
173            .await
174            .map_err(MacBackendError::Send)
175    }
176
177    async fn fill_random(&self, dest: &mut [u8]) {
178        self.fill_random(dest).await
179    }
180
181    async fn now_ms(&self) -> u64 {
182        self.now_ms().await
183    }
184
185    #[cfg(feature = "software-crypto")]
186    async fn register_ephemeral(
187        &self,
188        parent: LocalIdentityId,
189        identity: umsh_crypto::software::SoftwareIdentity,
190    ) -> Result<LocalIdentityId, MacBackendError<Self::SendError, Self::CapacityError>> {
191        self.register_ephemeral(parent, identity)
192            .await
193            .map_err(MacBackendError::Capacity)
194    }
195
196    #[cfg(feature = "software-crypto")]
197    async fn remove_ephemeral(&self, id: LocalIdentityId) -> bool {
198        self.remove_ephemeral(id).await
199    }
200}