1use core::cell::RefCell;
2
3use rand::Rng;
4use umsh_core::{ChannelId, ChannelKey, PublicKey};
5use umsh_hal::{Clock, CounterStore};
6
7use crate::{
8 CapacityError, DEFAULT_ACKS, DEFAULT_CHANNELS, DEFAULT_DUP, DEFAULT_FRAME, DEFAULT_IDENTITIES,
9 DEFAULT_PEERS, DEFAULT_TX, Platform,
10 coordinator::{CounterPersistenceError, LocalIdentityId, Mac, MacError, SendError},
11 peers::PeerId,
12 send::{SendOptions, SendReceipt},
13};
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq)]
17pub enum MacHandleError<E> {
18 Busy,
20 Inner(E),
22}
23
24pub struct MacHandle<
30 'a,
31 P: Platform,
32 const IDENTITIES: usize = DEFAULT_IDENTITIES,
33 const PEERS: usize = DEFAULT_PEERS,
34 const CHANNELS: usize = DEFAULT_CHANNELS,
35 const ACKS: usize = DEFAULT_ACKS,
36 const TX: usize = DEFAULT_TX,
37 const FRAME: usize = DEFAULT_FRAME,
38 const DUP: usize = DEFAULT_DUP,
39> {
40 mac: &'a RefCell<Mac<P, IDENTITIES, PEERS, CHANNELS, ACKS, TX, FRAME, DUP>>,
41}
42
43impl<
44 'a,
45 P: Platform,
46 const IDENTITIES: usize,
47 const PEERS: usize,
48 const CHANNELS: usize,
49 const ACKS: usize,
50 const TX: usize,
51 const FRAME: usize,
52 const DUP: usize,
53> Copy for MacHandle<'a, P, IDENTITIES, PEERS, CHANNELS, ACKS, TX, FRAME, DUP>
54{
55}
56
57impl<
58 'a,
59 P: Platform,
60 const IDENTITIES: usize,
61 const PEERS: usize,
62 const CHANNELS: usize,
63 const ACKS: usize,
64 const TX: usize,
65 const FRAME: usize,
66 const DUP: usize,
67> Clone for MacHandle<'a, P, IDENTITIES, PEERS, CHANNELS, ACKS, TX, FRAME, DUP>
68{
69 fn clone(&self) -> Self {
70 *self
71 }
72}
73
74impl<
75 'a,
76 P: Platform,
77 const IDENTITIES: usize,
78 const PEERS: usize,
79 const CHANNELS: usize,
80 const ACKS: usize,
81 const TX: usize,
82 const FRAME: usize,
83 const DUP: usize,
84> MacHandle<'a, P, IDENTITIES, PEERS, CHANNELS, ACKS, TX, FRAME, DUP>
85{
86 pub fn new(
88 mac: &'a RefCell<Mac<P, IDENTITIES, PEERS, CHANNELS, ACKS, TX, FRAME, DUP>>,
89 ) -> Self {
90 Self { mac }
91 }
92
93 pub fn add_identity(
95 &self,
96 identity: P::Identity,
97 ) -> Result<LocalIdentityId, MacHandleError<CapacityError>> {
98 self.with_mac(|mac| mac.add_identity(identity))
99 }
100
101 pub async fn load_persisted_counter(
103 &self,
104 id: LocalIdentityId,
105 ) -> Result<
106 u32,
107 MacHandleError<CounterPersistenceError<<P::CounterStore as CounterStore>::Error>>,
108 > {
109 let mut mac = self
110 .mac
111 .try_borrow_mut()
112 .map_err(|_| MacHandleError::Busy)?;
113 mac.load_persisted_counter(id)
114 .await
115 .map_err(MacHandleError::Inner)
116 }
117
118 pub async fn service_counter_persistence(
120 &self,
121 ) -> Result<usize, MacHandleError<<P::CounterStore as CounterStore>::Error>> {
122 let mut mac = self
123 .mac
124 .try_borrow_mut()
125 .map_err(|_| MacHandleError::Busy)?;
126 mac.service_counter_persistence()
127 .await
128 .map_err(MacHandleError::Inner)
129 }
130
131 pub fn add_peer(&self, key: PublicKey) -> Result<PeerId, MacHandleError<CapacityError>> {
133 self.with_mac(|mac| mac.add_peer(key))
134 }
135
136 pub fn add_channel(&self, key: ChannelKey) -> Result<(), MacHandleError<CapacityError>> {
138 self.with_mac(|mac| mac.add_channel(key))
139 }
140
141 pub fn add_named_channel(&self, name: &str) -> Result<(), MacHandleError<CapacityError>> {
143 self.with_mac(|mac| mac.add_named_channel(name))
144 }
145
146 pub fn auto_register_full_key_peers(
148 &self,
149 ) -> Result<bool, MacHandleError<core::convert::Infallible>> {
150 self.with_mac(|mac| Ok(mac.auto_register_full_key_peers()))
151 }
152
153 pub fn set_auto_register_full_key_peers(
155 &self,
156 enabled: bool,
157 ) -> Result<(), MacHandleError<core::convert::Infallible>> {
158 self.with_mac(|mac| {
159 mac.set_auto_register_full_key_peers(enabled);
160 Ok(())
161 })
162 }
163
164 #[cfg(any(feature = "unsafe-advanced", test))]
169 pub(crate) fn install_pairwise_keys(
170 &self,
171 identity_id: LocalIdentityId,
172 peer_id: PeerId,
173 pairwise_keys: umsh_crypto::PairwiseKeys,
174 ) -> Result<Option<crate::peers::PeerCryptoState>, MacHandleError<SendError>> {
175 self.with_mac(|mac| mac.install_pairwise_keys(identity_id, peer_id, pairwise_keys))
176 }
177
178 #[cfg(feature = "unsafe-advanced")]
185 pub fn install_pairwise_keys_advanced(
186 &self,
187 identity_id: LocalIdentityId,
188 peer_id: PeerId,
189 pairwise_keys: umsh_crypto::PairwiseKeys,
190 ) -> Result<Option<crate::peers::PeerCryptoState>, MacHandleError<SendError>> {
191 self.install_pairwise_keys(identity_id, peer_id, pairwise_keys)
192 }
193
194 pub async fn send_broadcast(
198 &self,
199 from: LocalIdentityId,
200 payload: &[u8],
201 options: &SendOptions,
202 ) -> Result<SendReceipt, MacHandleError<SendError>> {
203 let mut mac = self
204 .mac
205 .try_borrow_mut()
206 .map_err(|_| MacHandleError::Busy)?;
207 mac.send_broadcast(from, payload, options)
208 .await
209 .map_err(MacHandleError::Inner)
210 }
211
212 pub async fn send_multicast(
216 &self,
217 from: LocalIdentityId,
218 channel: &ChannelId,
219 payload: &[u8],
220 options: &SendOptions,
221 ) -> Result<SendReceipt, MacHandleError<SendError>> {
222 let mut mac = self
223 .mac
224 .try_borrow_mut()
225 .map_err(|_| MacHandleError::Busy)?;
226 mac.send_multicast(from, channel, payload, options)
227 .await
228 .map_err(MacHandleError::Inner)
229 }
230
231 pub async fn send_unicast(
235 &self,
236 from: LocalIdentityId,
237 dst: &PublicKey,
238 payload: &[u8],
239 options: &SendOptions,
240 ) -> Result<Option<SendReceipt>, MacHandleError<SendError>> {
241 let mut mac = self
242 .mac
243 .try_borrow_mut()
244 .map_err(|_| MacHandleError::Busy)?;
245 mac.send_unicast(from, dst, payload, options)
246 .await
247 .map_err(MacHandleError::Inner)
248 }
249
250 pub async fn send_blind_unicast(
254 &self,
255 from: LocalIdentityId,
256 dst: &PublicKey,
257 channel: &ChannelId,
258 payload: &[u8],
259 options: &SendOptions,
260 ) -> Result<Option<SendReceipt>, MacHandleError<SendError>> {
261 let mut mac = self
262 .mac
263 .try_borrow_mut()
264 .map_err(|_| MacHandleError::Busy)?;
265 mac.send_blind_unicast(from, dst, channel, payload, options)
266 .await
267 .map_err(MacHandleError::Inner)
268 }
269
270 pub async fn next_event(
272 &self,
273 on_event: impl FnMut(LocalIdentityId, crate::MacEventRef<'_>),
274 ) -> Result<(), MacHandleError<MacError<<P::Radio as umsh_hal::Radio>::Error>>> {
275 let mut mac = self
276 .mac
277 .try_borrow_mut()
278 .map_err(|_| MacHandleError::Busy)?;
279 mac.next_event(on_event)
280 .await
281 .map_err(MacHandleError::Inner)
282 }
283
284 pub async fn run(
290 &self,
291 mut on_event: impl FnMut(LocalIdentityId, crate::MacEventRef<'_>),
292 ) -> Result<(), MacHandleError<MacError<<P::Radio as umsh_hal::Radio>::Error>>> {
293 loop {
294 self.next_event(&mut on_event).await?;
295 }
296 }
297
298 pub async fn run_quiet(
300 &self,
301 ) -> Result<(), MacHandleError<MacError<<P::Radio as umsh_hal::Radio>::Error>>> {
302 self.run(|_, _| {}).await
303 }
304
305 pub fn fill_random(
307 &self,
308 dest: &mut [u8],
309 ) -> Result<(), MacHandleError<core::convert::Infallible>> {
310 self.with_mac(|mac| {
311 mac.rng_mut().fill_bytes(dest);
312 Ok(())
313 })
314 }
315
316 pub fn now_ms(&self) -> Result<u64, MacHandleError<core::convert::Infallible>> {
318 self.with_mac(|mac| Ok(mac.clock().now_ms()))
319 }
320
321 #[cfg(feature = "software-crypto")]
322 pub fn register_ephemeral(
326 &self,
327 parent: LocalIdentityId,
328 identity: umsh_crypto::software::SoftwareIdentity,
329 ) -> Result<LocalIdentityId, MacHandleError<CapacityError>> {
330 self.with_mac(|mac| mac.register_ephemeral(parent, identity))
331 }
332
333 #[cfg(feature = "software-crypto")]
334 pub fn remove_ephemeral(
336 &self,
337 id: LocalIdentityId,
338 ) -> Result<bool, MacHandleError<core::convert::Infallible>> {
339 self.with_mac(|mac| Ok(mac.remove_ephemeral(id)))
340 }
341
342 pub fn cancel_pending_ack(&self, identity_id: LocalIdentityId, receipt: SendReceipt) -> bool {
347 self.mac
348 .try_borrow_mut()
349 .map(|mut mac| mac.cancel_pending_ack(identity_id, receipt))
350 .unwrap_or(false)
351 }
352
353 fn with_mac<T, E>(
354 &self,
355 f: impl FnOnce(&mut Mac<P, IDENTITIES, PEERS, CHANNELS, ACKS, TX, FRAME, DUP>) -> Result<T, E>,
356 ) -> Result<T, MacHandleError<E>> {
357 let mut mac = self
358 .mac
359 .try_borrow_mut()
360 .map_err(|_| MacHandleError::Busy)?;
361 f(&mut mac).map_err(MacHandleError::Inner)
362 }
363}