1use alloc::boxed::Box;
2use alloc::rc::Rc;
3use alloc::vec::Vec;
4use core::cell::RefCell;
5use core::num::NonZeroU32;
6
7use umsh_core::{ChannelId, NodeHint, PublicKey, RouterHint};
8use umsh_mac::{CachedRoute, LocalIdentityId, SendOptions};
9
10#[cfg(feature = "software-crypto")]
11use crate::channel::Channel;
12use crate::dispatch::EventDispatcher;
13use crate::identity_responder::{
14 IdentityRequestContext, IdentityResponder, IdentityResponsePlan, NodeIdentityProfile,
15 RespondDecision, default_respond_policy,
16};
17use crate::mac::MacBackend;
18use crate::peer::PeerConnection;
19use crate::peer_repeaters::{self, PeerRepeaterTable};
20#[cfg(feature = "software-crypto")]
21use crate::pfs::{PfsSessionManager, PfsState};
22use crate::receive::ReceivedPacketRef;
23use crate::ticket::{SendProgressTicket, SendToken};
24use crate::transport::Transport;
25use crate::{AppEncodeError, OwnedMacCommand};
26
27const PEER_REPEATERS_RESPONSE_BUDGET: usize = 160;
34
35const PEER_REPEATERS_CURSOR_LEN: usize = 3;
44
45pub(crate) struct NodeMembership {
48 #[cfg(feature = "software-crypto")]
49 pub channels: Vec<ChannelMembershipEntry>,
50}
51
52#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
53pub(crate) struct SubscriptionHandle(NonZeroU32);
54
55pub struct Subscription {
59 cancel: Rc<RefCell<Option<Box<dyn FnMut() -> bool>>>>,
60}
61
62impl Subscription {
63 pub(crate) fn new(cancel: impl FnMut() -> bool + 'static) -> Self {
64 Self {
65 cancel: Rc::new(RefCell::new(Some(Box::new(cancel)))),
66 }
67 }
68
69 pub fn unsubscribe(self) -> bool {
71 Self::run_cancel(&self.cancel)
72 }
73
74 fn run_cancel(cancel: &Rc<RefCell<Option<Box<dyn FnMut() -> bool>>>>) -> bool {
75 let Some(mut cancel) = cancel.borrow_mut().take() else {
76 return false;
77 };
78 cancel()
79 }
80}
81
82impl Drop for Subscription {
83 fn drop(&mut self) {
84 let _ = Self::run_cancel(&self.cancel);
85 }
86}
87
88pub(crate) struct HandlerTable<T> {
89 slots: Vec<Option<T>>,
90}
91
92impl<T> Default for HandlerTable<T> {
93 fn default() -> Self {
94 Self { slots: Vec::new() }
95 }
96}
97
98impl<T> HandlerTable<T> {
99 pub(crate) fn insert(&mut self, handler: T) -> SubscriptionHandle {
100 if let Some((index, slot)) = self
101 .slots
102 .iter_mut()
103 .enumerate()
104 .find(|(_, slot)| slot.is_none())
105 {
106 *slot = Some(handler);
107 return SubscriptionHandle(NonZeroU32::new((index + 1) as u32).unwrap());
108 }
109 self.slots.push(Some(handler));
110 SubscriptionHandle(NonZeroU32::new(self.slots.len() as u32).unwrap())
111 }
112
113 pub(crate) fn remove(&mut self, handle: SubscriptionHandle) -> bool {
114 let index = handle.0.get() as usize - 1;
115 let Some(slot) = self.slots.get_mut(index) else {
116 return false;
117 };
118 slot.take().is_some()
119 }
120
121 fn any_mut(&mut self, mut f: impl FnMut(&mut T) -> bool) -> bool {
122 for slot in &mut self.slots {
123 let Some(handler) = slot.as_mut() else {
124 continue;
125 };
126 if f(handler) {
127 return true;
128 }
129 }
130 false
131 }
132
133 fn for_each_mut(&mut self, mut f: impl FnMut(&mut T)) {
134 for slot in &mut self.slots {
135 let Some(handler) = slot.as_mut() else {
136 continue;
137 };
138 f(handler);
139 }
140 }
141}
142
143pub(crate) struct PendingPing {
144 pub nonce: u16,
145 pub peer: PublicKey,
146 pub sent_at_ms: u64,
147 pub deadline_ms: u64,
148}
149
150#[derive(Clone, Debug, PartialEq, Eq)]
156pub struct PongMetadata {
157 pub round_trip_ms: u64,
158 pub hop_count: Option<u8>,
164 pub route_hints: Vec<RouterHint>,
165 pub rssi_dbm: Option<i16>,
166 pub snr_centibels: Option<i16>,
167 pub lqi: Option<u8>,
168}
169
170pub(crate) struct PeerSubscriptions {
171 peer: PublicKey,
172 pub(crate) receive_handlers: HandlerTable<Box<dyn FnMut(&ReceivedPacketRef<'_>) -> bool>>,
173 pub(crate) ack_received_handlers: HandlerTable<Box<dyn FnMut(SendToken)>>,
174 pub(crate) ack_timeout_handlers: HandlerTable<Box<dyn FnMut(SendToken)>>,
175 pub(crate) pfs_established_handlers: HandlerTable<Box<dyn FnMut()>>,
176 pub(crate) pfs_ended_handlers: HandlerTable<Box<dyn FnMut()>>,
177 pub(crate) pong_handlers: HandlerTable<Box<dyn FnMut(u64)>>,
178 pub(crate) ping_timeout_handlers: HandlerTable<Box<dyn FnMut()>>,
179}
180
181impl PeerSubscriptions {
182 fn new(peer: PublicKey) -> Self {
183 Self {
184 peer,
185 receive_handlers: HandlerTable::default(),
186 ack_received_handlers: HandlerTable::default(),
187 ack_timeout_handlers: HandlerTable::default(),
188 pfs_established_handlers: HandlerTable::default(),
189 pfs_ended_handlers: HandlerTable::default(),
190 pong_handlers: HandlerTable::default(),
191 ping_timeout_handlers: HandlerTable::default(),
192 }
193 }
194}
195
196pub(crate) struct LocalNodeState {
197 receive_handlers: HandlerTable<Box<dyn FnMut(&ReceivedPacketRef<'_>) -> bool>>,
198 node_discovered_handlers: HandlerTable<Box<dyn FnMut(PublicKey, Option<&str>)>>,
199 beacon_handlers: HandlerTable<Box<dyn FnMut(NodeHint, Option<PublicKey>)>>,
200 mac_command_handlers: HandlerTable<Box<dyn FnMut(PublicKey, &OwnedMacCommand)>>,
201 transmitted_handlers: HandlerTable<Box<dyn FnMut(&[u8])>>,
202 ack_received_handlers: HandlerTable<Box<dyn FnMut(PublicKey, SendToken)>>,
203 ack_timeout_handlers: HandlerTable<Box<dyn FnMut(PublicKey, SendToken)>>,
204 pfs_established_handlers: HandlerTable<Box<dyn FnMut(PublicKey)>>,
205 pfs_ended_handlers: HandlerTable<Box<dyn FnMut(PublicKey)>>,
206 pfs_failed_handlers: HandlerTable<Box<dyn FnMut(PublicKey, PfsFailure)>>,
207 pong_handlers: HandlerTable<Box<dyn FnMut(PublicKey, u64)>>,
208 pong_metadata_handlers: HandlerTable<Box<dyn FnMut(PublicKey, &PongMetadata)>>,
209 ping_timeout_handlers: HandlerTable<Box<dyn FnMut(PublicKey)>>,
210 pending_pings: Vec<PendingPing>,
211 peer_subscriptions: Vec<PeerSubscriptions>,
212 identity_responder: Option<IdentityResponder>,
213 peer_repeaters: PeerRepeaterTable,
216 peer_repeaters_responder: bool,
217 #[cfg(feature = "software-crypto")]
218 pfs: PfsSessionManager,
219}
220
221impl LocalNodeState {
222 pub(crate) fn new() -> Self {
223 Self {
224 receive_handlers: HandlerTable::default(),
225 node_discovered_handlers: HandlerTable::default(),
226 beacon_handlers: HandlerTable::default(),
227 mac_command_handlers: HandlerTable::default(),
228 transmitted_handlers: HandlerTable::default(),
229 ack_received_handlers: HandlerTable::default(),
230 ack_timeout_handlers: HandlerTable::default(),
231 pfs_established_handlers: HandlerTable::default(),
232 pfs_ended_handlers: HandlerTable::default(),
233 pfs_failed_handlers: HandlerTable::default(),
234 pong_handlers: HandlerTable::default(),
235 pong_metadata_handlers: HandlerTable::default(),
236 ping_timeout_handlers: HandlerTable::default(),
237 pending_pings: Vec::new(),
238 peer_subscriptions: Vec::new(),
239 identity_responder: None,
240 peer_repeaters: PeerRepeaterTable::new(),
241 peer_repeaters_responder: false,
242 #[cfg(feature = "software-crypto")]
243 pfs: PfsSessionManager::new(),
244 }
245 }
246
247 pub(crate) fn peer_subscriptions_mut(&mut self, peer: PublicKey) -> &mut PeerSubscriptions {
248 if let Some(index) = self
249 .peer_subscriptions
250 .iter()
251 .position(|entry| entry.peer == peer)
252 {
253 return &mut self.peer_subscriptions[index];
254 }
255 self.peer_subscriptions.push(PeerSubscriptions::new(peer));
256 self.peer_subscriptions
257 .last_mut()
258 .expect("peer subscriptions just inserted")
259 }
260
261 pub(crate) fn find_peer_subscriptions_mut(
262 &mut self,
263 peer: PublicKey,
264 ) -> Option<&mut PeerSubscriptions> {
265 self.peer_subscriptions
266 .iter_mut()
267 .find(|entry| entry.peer == peer)
268 }
269}
270
271#[derive(Clone, Copy, Debug, PartialEq, Eq)]
272#[cfg(feature = "software-crypto")]
273pub enum PfsStatus {
274 Inactive,
275 Requested,
276 Active {
277 local_ephemeral_id: LocalIdentityId,
278 peer_ephemeral: PublicKey,
279 expires_ms: u64,
280 },
281}
282
283#[derive(Clone, Copy, Debug, PartialEq, Eq)]
284pub(crate) enum PfsLifecycle {
285 Established(PublicKey),
286 Ended(PublicKey),
287}
288
289#[derive(Clone, Copy, Debug, PartialEq, Eq)]
293pub enum PfsFailure {
294 Capacity,
298 SessionMissing,
300 Crypto,
302 Send,
304 Timeout,
307 Other,
309}
310
311#[cfg(feature = "software-crypto")]
312pub(crate) struct ChannelMembershipEntry {
313 pub channel: Channel,
314 pub generation: u64,
317 pub active: bool,
319}
320
321impl NodeMembership {
322 pub fn new() -> Self {
323 Self {
324 #[cfg(feature = "software-crypto")]
325 channels: Vec::new(),
326 }
327 }
328}
329
330#[derive(Clone, PartialEq, Eq)]
332pub enum NodeError<M: MacBackend> {
333 Mac(crate::mac::MacBackendError<M::SendError, M::CapacityError>),
335 ChannelLeft,
337 PeerMissing,
339 AppEncode(AppEncodeError),
341 #[cfg(feature = "software-crypto")]
343 PfsSessionMissing,
344 #[cfg(feature = "software-crypto")]
346 PfsSessionTableFull,
347 #[cfg(feature = "software-crypto")]
349 Crypto(umsh_crypto::CryptoError),
350}
351
352impl<M: MacBackend> NodeError<M> {
353 pub(crate) fn pfs_failure(&self) -> PfsFailure {
357 use crate::mac::MacBackendError;
358 match self {
359 NodeError::Mac(MacBackendError::Capacity(_)) => PfsFailure::Capacity,
360 NodeError::Mac(MacBackendError::Send(_)) => PfsFailure::Send,
361 #[cfg(feature = "software-crypto")]
362 NodeError::PfsSessionTableFull => PfsFailure::Capacity,
363 #[cfg(feature = "software-crypto")]
364 NodeError::PfsSessionMissing => PfsFailure::SessionMissing,
365 #[cfg(feature = "software-crypto")]
366 NodeError::Crypto(_) => PfsFailure::Crypto,
367 _ => PfsFailure::Other,
368 }
369 }
370}
371
372impl<M> core::fmt::Debug for NodeError<M>
373where
374 M: MacBackend,
375 M::SendError: core::fmt::Debug,
376 M::CapacityError: core::fmt::Debug,
377{
378 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
379 match self {
380 Self::Mac(e) => f.debug_tuple("Mac").field(e).finish(),
381 Self::ChannelLeft => f.write_str("ChannelLeft"),
382 Self::PeerMissing => f.write_str("PeerMissing"),
383 Self::AppEncode(e) => f.debug_tuple("AppEncode").field(e).finish(),
384 #[cfg(feature = "software-crypto")]
385 Self::PfsSessionMissing => f.write_str("PfsSessionMissing"),
386 #[cfg(feature = "software-crypto")]
387 Self::PfsSessionTableFull => f.write_str("PfsSessionTableFull"),
388 #[cfg(feature = "software-crypto")]
389 Self::Crypto(e) => f.debug_tuple("Crypto").field(e).finish(),
390 }
391 }
392}
393
394impl<M: MacBackend> From<crate::mac::MacBackendError<M::SendError, M::CapacityError>>
395 for NodeError<M>
396{
397 fn from(e: crate::mac::MacBackendError<M::SendError, M::CapacityError>) -> Self {
398 Self::Mac(e)
399 }
400}
401
402impl<M: MacBackend> From<AppEncodeError> for NodeError<M> {
403 fn from(e: AppEncodeError) -> Self {
404 Self::AppEncode(e)
405 }
406}
407
408#[cfg(feature = "software-crypto")]
409impl<M: MacBackend> From<umsh_crypto::CryptoError> for NodeError<M> {
410 fn from(e: umsh_crypto::CryptoError) -> Self {
411 Self::Crypto(e)
412 }
413}
414
415#[derive(Clone)]
421pub struct LocalNode<M: MacBackend> {
422 identity_id: LocalIdentityId,
423 mac: M,
424 dispatcher: Rc<RefCell<EventDispatcher>>,
425 #[allow(dead_code)] membership: Rc<RefCell<NodeMembership>>,
427 state: Rc<RefCell<LocalNodeState>>,
428}
429
430impl<M: MacBackend> LocalNode<M> {
431 pub(crate) fn new(
433 identity_id: LocalIdentityId,
434 mac: M,
435 dispatcher: Rc<RefCell<EventDispatcher>>,
436 membership: Rc<RefCell<NodeMembership>>,
437 state: Rc<RefCell<LocalNodeState>>,
438 ) -> Self {
439 Self {
440 identity_id,
441 mac,
442 dispatcher,
443 membership,
444 state,
445 }
446 }
447
448 pub fn identity_id(&self) -> LocalIdentityId {
450 self.identity_id
451 }
452
453 pub async fn peer(&self, key: PublicKey) -> Result<PeerConnection<Self>, NodeError<M>> {
455 self.mac.add_peer(key).await?;
456 Ok(PeerConnection::new(self.clone(), key))
457 }
458
459 pub async fn remove_peer(&self, key: &PublicKey) -> bool {
464 let removed = self.mac.remove_peer(key).await;
465 let mut state = self.state.borrow_mut();
466 state.pending_pings.retain(|ping| ping.peer != *key);
467 state.peer_subscriptions.retain(|entry| entry.peer != *key);
468 removed
469 }
470
471 pub async fn frame_counter(&self) -> Option<u32> {
473 self.mac.frame_counter(self.identity_id).await
474 }
475
476 pub async fn persisted_frame_counter(&self) -> Option<u32> {
478 self.mac.persisted_frame_counter(self.identity_id).await
479 }
480
481 pub async fn for_each_peer(&self, f: &mut dyn FnMut(PublicKey)) {
485 self.mac.for_each_peer(f).await
486 }
487
488 pub async fn for_each_peer_counter(&self, f: &mut dyn FnMut(PublicKey, u32, u32)) {
491 self.mac.for_each_peer_counter(self.identity_id, f).await
492 }
493
494 pub async fn peer_route(&self, peer: &PublicKey) -> Option<CachedRoute> {
499 self.mac.peer_route(peer).await
500 }
501
502 pub async fn clear_peer_route(&self, peer: &PublicKey) -> bool {
507 self.mac.clear_peer_route(peer).await
508 }
509
510 pub async fn restore_peer_route(&self, peer: &PublicKey, route: CachedRoute) -> bool {
516 self.mac.restore_peer_route(peer, route).await
517 }
518
519 fn add_receive_handler<F>(&self, handler: F) -> SubscriptionHandle
520 where
521 F: FnMut(&ReceivedPacketRef<'_>) -> bool + 'static,
522 {
523 self.state
524 .borrow_mut()
525 .receive_handlers
526 .insert(Box::new(handler))
527 }
528
529 pub fn on_receive<F>(&self, handler: F) -> Subscription
530 where
531 F: FnMut(&ReceivedPacketRef<'_>) -> bool + 'static,
532 {
533 let handle = self.add_receive_handler(handler);
534 let state = self.state.clone();
535 Subscription::new(move || state.borrow_mut().receive_handlers.remove(handle))
536 }
537
538 fn add_node_discovered_handler<F>(&self, handler: F) -> SubscriptionHandle
539 where
540 F: FnMut(PublicKey, Option<&str>) + 'static,
541 {
542 self.state
543 .borrow_mut()
544 .node_discovered_handlers
545 .insert(Box::new(handler))
546 }
547
548 pub fn on_node_discovered<F>(&self, handler: F) -> Subscription
549 where
550 F: FnMut(PublicKey, Option<&str>) + 'static,
551 {
552 let handle = self.add_node_discovered_handler(handler);
553 let state = self.state.clone();
554 Subscription::new(move || state.borrow_mut().node_discovered_handlers.remove(handle))
555 }
556
557 fn add_beacon_handler<F>(&self, handler: F) -> SubscriptionHandle
558 where
559 F: FnMut(NodeHint, Option<PublicKey>) + 'static,
560 {
561 self.state
562 .borrow_mut()
563 .beacon_handlers
564 .insert(Box::new(handler))
565 }
566
567 pub fn on_beacon<F>(&self, handler: F) -> Subscription
568 where
569 F: FnMut(NodeHint, Option<PublicKey>) + 'static,
570 {
571 let handle = self.add_beacon_handler(handler);
572 let state = self.state.clone();
573 Subscription::new(move || state.borrow_mut().beacon_handlers.remove(handle))
574 }
575
576 fn add_mac_command_handler<F>(&self, handler: F) -> SubscriptionHandle
577 where
578 F: FnMut(PublicKey, &OwnedMacCommand) + 'static,
579 {
580 self.state
581 .borrow_mut()
582 .mac_command_handlers
583 .insert(Box::new(handler))
584 }
585
586 pub fn on_mac_command<F>(&self, handler: F) -> Subscription
587 where
588 F: FnMut(PublicKey, &OwnedMacCommand) + 'static,
589 {
590 let handle = self.add_mac_command_handler(handler);
591 let state = self.state.clone();
592 Subscription::new(move || state.borrow_mut().mac_command_handlers.remove(handle))
593 }
594
595 pub fn enable_identity_responder<P>(&self, profile: NodeIdentityProfile, policy: P)
605 where
606 P: FnMut(&IdentityRequestContext<'_>) -> RespondDecision + 'static,
607 {
608 self.state.borrow_mut().identity_responder =
609 Some(IdentityResponder::new(profile, Box::new(policy)));
610 }
611
612 pub fn enable_identity_responder_default(&self, profile: NodeIdentityProfile) {
615 self.enable_identity_responder(profile, default_respond_policy);
616 }
617
618 pub fn disable_identity_responder(&self) {
620 self.state.borrow_mut().identity_responder = None;
621 }
622
623 pub fn update_identity_profile(&self, f: impl FnOnce(&mut NodeIdentityProfile)) {
627 if let Some(responder) = self.state.borrow_mut().identity_responder.as_mut() {
628 f(&mut responder.profile);
629 }
630 }
631
632 pub fn with_identity_profile<R>(&self, f: impl FnOnce(&NodeIdentityProfile) -> R) -> Option<R> {
641 self.state
642 .borrow()
643 .identity_responder
644 .as_ref()
645 .map(|responder| f(&responder.profile))
646 }
647
648 pub(crate) fn evaluate_identity_request(
653 &self,
654 packet: &ReceivedPacketRef<'_>,
655 from: PublicKey,
656 options: &[u8],
657 now_ms: u64,
658 ) -> Option<IdentityResponsePlan> {
659 let filters = crate::mac_command::IdentityRequestFilters::new(options);
670 if matches!(
671 packet.packet_family(),
672 crate::PacketFamily::Broadcast | crate::PacketFamily::Multicast
673 ) {
674 if packet.source_route().is_some_and(|route| !route.is_empty()) {
675 return None;
676 }
677 if !filters.hint_filtered() && packet.flood_hops().is_some_and(|hops| hops.0 != 0) {
678 return None;
679 }
680 }
681 let ctx = IdentityRequestContext {
682 from_key: from,
683 from_hint: packet.from_hint(),
684 source_authenticated: packet.source_authenticated(),
685 has_full_source: packet.has_full_source(),
686 channel: packet.channel().map(|c| c.id()),
687 family: packet.packet_family(),
688 filters,
689 rssi: packet.rssi(),
690 snr: packet.snr(),
691 trace_route: packet.trace_route().unwrap_or(&[]),
692 };
693 self.state
694 .borrow_mut()
695 .identity_responder
696 .as_mut()?
697 .evaluate(&ctx, now_ms)
698 }
699
700 pub async fn send_response(
708 &self,
709 to: &PublicKey,
710 channel: Option<ChannelId>,
711 payload: &[u8],
712 options: &SendOptions,
713 ) -> Result<Option<umsh_mac::SendReceipt>, crate::MacBackendError<M::SendError, M::CapacityError>>
714 {
715 match channel {
716 Some(channel) => {
717 self.mac
718 .send_blind_unicast(self.identity_id, to, &channel, payload, options)
719 .await
720 }
721 None => {
722 self.mac
723 .send_unicast(self.identity_id, to, payload, options)
724 .await
725 }
726 }
727 }
728
729 pub(crate) async fn send_identity_response(&self, plan: IdentityResponsePlan) {
736 let unrouted = || {
737 let options = SendOptions::default();
738 if plan.full_source {
739 options.with_full_source()
740 } else {
741 options
742 }
743 };
744 let mut options = if plan.route.is_empty() {
754 unrouted()
755 } else {
756 unrouted()
757 .try_with_source_route(&plan.route)
758 .unwrap_or_else(|_| unrouted())
759 };
760 if plan.no_flood {
761 options = options.no_flood();
765 }
766 if plan.delayed {
767 let mut jitter = [0u8; 2];
772 self.mac.fill_random(&mut jitter).await;
773 let delay = u16::from_be_bytes(jitter)
774 % (crate::identity_responder::RESPONSE_MAX_DELAY_MS
775 - crate::identity_responder::RESPONSE_MIN_DELAY_MS
776 + 1)
777 + crate::identity_responder::RESPONSE_MIN_DELAY_MS;
778 options = options.with_tx_delay_ms(delay);
779 }
780 let _ = self.mac.ensure_transient_peer(&plan.to).await;
785 let _ = self
786 .send_response(&plan.to, plan.channel, &plan.framed, &options)
787 .await;
788 }
789
790 pub fn enable_peer_repeaters_responder(&self) {
797 self.state.borrow_mut().peer_repeaters_responder = true;
798 }
799
800 pub fn disable_peer_repeaters_responder(&self) {
801 self.state.borrow_mut().peer_repeaters_responder = false;
802 }
803
804 pub fn peer_repeaters_responder_enabled(&self) -> bool {
805 self.state.borrow().peer_repeaters_responder
806 }
807
808 pub(crate) fn observe_peer_identity(
810 &self,
811 from: PublicKey,
812 identity: &crate::NodeIdentityPayload,
813 now_ms: u64,
814 ) {
815 self.state
816 .borrow_mut()
817 .peer_repeaters
818 .observe_identity(&from, identity, now_ms);
819 }
820
821 pub async fn peer_repeaters(&self) -> Vec<peer_repeaters::MergedPeerRepeater> {
824 let now_ms = self.mac.now_ms().await;
825 let mut observations = Vec::new();
826 self.mac
827 .for_each_transmitter_observation(&mut |observation| observations.push(observation))
828 .await;
829 let identities = self.state.borrow().peer_repeaters.clone();
832 peer_repeaters::merge(&identities, observations.iter(), now_ms)
833 }
834
835 pub(crate) async fn answer_peer_repeaters_request(
841 &self,
842 to: PublicKey,
843 channel: Option<ChannelId>,
844 request: &[u8],
845 ) {
846 if !self.peer_repeaters_responder_enabled() {
847 return;
848 }
849 let view = crate::mac_command::PeerRepeatersRequestView::new(request);
850 let generation = self.state.borrow().peer_repeaters.generation();
851 let peers = self.peer_repeaters().await;
852
853 let start = match view.cursor() {
857 Some([high, low, index]) if u16::from_be_bytes([*high, *low]) == generation => {
858 usize::from(*index)
859 }
860 _ => 0,
861 };
862 let total = u8::try_from(peers.len()).unwrap_or(u8::MAX);
863
864 let mut builder =
865 crate::mac_command::PeerRepeatersResponseBuilder::new(PEER_REPEATERS_RESPONSE_BUDGET)
866 .total(total)
867 .reserve_cursor(PEER_REPEATERS_CURSOR_LEN);
868 if let Some(nonce) = view.nonce() {
869 builder = builder.nonce(nonce);
870 }
871
872 let mut next = start;
873 for peer in peers.iter().skip(start) {
874 let regions: Vec<u8> = peer.regions.iter().flatten().copied().collect();
875 let entry = crate::mac_command::PeerRepeaterEntry {
876 hint: &peer.hint,
877 name: peer.name.as_deref(),
878 rssi_snr: match (peer.rssi_dbm, peer.snr) {
879 (Some(rssi), Some(snr)) => Some((rssi, snr)),
880 _ => None,
881 },
882 last_heard_min: peer.last_heard_min,
883 location: peer.location,
884 regions: ®ions,
885 };
886 match builder.try_push(&entry) {
889 Ok(true) => next += 1,
890 Ok(false) => break,
891 Err(_) => next += 1,
892 }
893 }
894 if next < peers.len() {
895 let [high, low] = generation.to_be_bytes();
896 builder = builder.cursor(&[high, low, u8::try_from(next).unwrap_or(u8::MAX)]);
897 }
898 let Ok(body) = builder.build() else {
899 return;
900 };
901
902 let mut framed = [0u8; PEER_REPEATERS_RESPONSE_BUDGET + 8];
905 framed[0] = umsh_core::PayloadType::MacCommand as u8;
906 let Ok(len) = crate::mac_command::encode(
907 &crate::mac_command::MacCommand::PeerRepeatersResponse { body: &body },
908 &mut framed[1..],
909 ) else {
910 return;
911 };
912 let _ = self.mac.ensure_transient_peer(&to).await;
913 let _ = self
914 .send_response(&to, channel, &framed[..len + 1], &SendOptions::default())
915 .await;
916 }
917
918 fn add_transmitted_handler<F>(&self, handler: F) -> SubscriptionHandle
919 where
920 F: FnMut(&[u8]) + 'static,
921 {
922 self.state
923 .borrow_mut()
924 .transmitted_handlers
925 .insert(Box::new(handler))
926 }
927
928 pub fn on_transmitted<F>(&self, handler: F) -> Subscription
930 where
931 F: FnMut(&[u8]) + 'static,
932 {
933 let handle = self.add_transmitted_handler(handler);
934 let state = self.state.clone();
935 Subscription::new(move || state.borrow_mut().transmitted_handlers.remove(handle))
936 }
937
938 fn add_ack_received_handler<F>(&self, handler: F) -> SubscriptionHandle
939 where
940 F: FnMut(PublicKey, SendToken) + 'static,
941 {
942 self.state
943 .borrow_mut()
944 .ack_received_handlers
945 .insert(Box::new(handler))
946 }
947
948 pub fn on_ack_received<F>(&self, handler: F) -> Subscription
949 where
950 F: FnMut(PublicKey, SendToken) + 'static,
951 {
952 let handle = self.add_ack_received_handler(handler);
953 let state = self.state.clone();
954 Subscription::new(move || state.borrow_mut().ack_received_handlers.remove(handle))
955 }
956
957 fn add_ack_timeout_handler<F>(&self, handler: F) -> SubscriptionHandle
958 where
959 F: FnMut(PublicKey, SendToken) + 'static,
960 {
961 self.state
962 .borrow_mut()
963 .ack_timeout_handlers
964 .insert(Box::new(handler))
965 }
966
967 pub fn on_ack_timeout<F>(&self, handler: F) -> Subscription
968 where
969 F: FnMut(PublicKey, SendToken) + 'static,
970 {
971 let handle = self.add_ack_timeout_handler(handler);
972 let state = self.state.clone();
973 Subscription::new(move || state.borrow_mut().ack_timeout_handlers.remove(handle))
974 }
975
976 fn add_pfs_established_handler<F>(&self, handler: F) -> SubscriptionHandle
977 where
978 F: FnMut(PublicKey) + 'static,
979 {
980 self.state
981 .borrow_mut()
982 .pfs_established_handlers
983 .insert(Box::new(handler))
984 }
985
986 pub fn on_pfs_established<F>(&self, handler: F) -> Subscription
987 where
988 F: FnMut(PublicKey) + 'static,
989 {
990 let handle = self.add_pfs_established_handler(handler);
991 let state = self.state.clone();
992 Subscription::new(move || state.borrow_mut().pfs_established_handlers.remove(handle))
993 }
994
995 fn add_pfs_ended_handler<F>(&self, handler: F) -> SubscriptionHandle
996 where
997 F: FnMut(PublicKey) + 'static,
998 {
999 self.state
1000 .borrow_mut()
1001 .pfs_ended_handlers
1002 .insert(Box::new(handler))
1003 }
1004
1005 pub fn on_pfs_ended<F>(&self, handler: F) -> Subscription
1006 where
1007 F: FnMut(PublicKey) + 'static,
1008 {
1009 let handle = self.add_pfs_ended_handler(handler);
1010 let state = self.state.clone();
1011 Subscription::new(move || state.borrow_mut().pfs_ended_handlers.remove(handle))
1012 }
1013
1014 fn add_pfs_failed_handler<F>(&self, handler: F) -> SubscriptionHandle
1015 where
1016 F: FnMut(PublicKey, PfsFailure) + 'static,
1017 {
1018 self.state
1019 .borrow_mut()
1020 .pfs_failed_handlers
1021 .insert(Box::new(handler))
1022 }
1023
1024 pub fn on_pfs_failed<F>(&self, handler: F) -> Subscription
1030 where
1031 F: FnMut(PublicKey, PfsFailure) + 'static,
1032 {
1033 let handle = self.add_pfs_failed_handler(handler);
1034 let state = self.state.clone();
1035 Subscription::new(move || state.borrow_mut().pfs_failed_handlers.remove(handle))
1036 }
1037
1038 fn add_pong_handler<F>(&self, handler: F) -> SubscriptionHandle
1039 where
1040 F: FnMut(PublicKey, u64) + 'static,
1041 {
1042 self.state
1043 .borrow_mut()
1044 .pong_handlers
1045 .insert(Box::new(handler))
1046 }
1047
1048 pub fn on_pong<F>(&self, handler: F) -> Subscription
1049 where
1050 F: FnMut(PublicKey, u64) + 'static,
1051 {
1052 let handle = self.add_pong_handler(handler);
1053 let state = self.state.clone();
1054 Subscription::new(move || state.borrow_mut().pong_handlers.remove(handle))
1055 }
1056
1057 pub fn on_pong_with_metadata<F>(&self, handler: F) -> Subscription
1058 where
1059 F: FnMut(PublicKey, &PongMetadata) + 'static,
1060 {
1061 let handle = self
1062 .state
1063 .borrow_mut()
1064 .pong_metadata_handlers
1065 .insert(Box::new(handler));
1066 let state = self.state.clone();
1067 Subscription::new(move || state.borrow_mut().pong_metadata_handlers.remove(handle))
1068 }
1069
1070 fn add_ping_timeout_handler<F>(&self, handler: F) -> SubscriptionHandle
1071 where
1072 F: FnMut(PublicKey) + 'static,
1073 {
1074 self.state
1075 .borrow_mut()
1076 .ping_timeout_handlers
1077 .insert(Box::new(handler))
1078 }
1079
1080 pub fn on_ping_timeout<F>(&self, handler: F) -> Subscription
1081 where
1082 F: FnMut(PublicKey) + 'static,
1083 {
1084 let handle = self.add_ping_timeout_handler(handler);
1085 let state = self.state.clone();
1086 Subscription::new(move || state.borrow_mut().ping_timeout_handlers.remove(handle))
1087 }
1088
1089 pub(crate) fn record_ping(
1090 &self,
1091 nonce: u16,
1092 peer: PublicKey,
1093 sent_at_ms: u64,
1094 deadline_ms: u64,
1095 ) {
1096 self.state.borrow_mut().pending_pings.push(PendingPing {
1097 nonce,
1098 peer,
1099 sent_at_ms,
1100 deadline_ms,
1101 });
1102 }
1103
1104 pub(crate) async fn now_ms(&self) -> u64 {
1105 self.mac.now_ms().await
1106 }
1107
1108 pub(crate) async fn fill_random(&self, dest: &mut [u8]) {
1109 self.mac.fill_random(dest).await
1110 }
1111
1112 pub(crate) fn match_pong(
1114 &self,
1115 from: PublicKey,
1116 data: &[u8],
1117 packet: &ReceivedPacketRef<'_>,
1118 now_ms: u64,
1119 ) {
1120 if data.len() < 2 {
1121 return;
1122 }
1123 let nonce = u16::from_be_bytes([data[0], data[1]]);
1124 let mut state = self.state.borrow_mut();
1125 let idx = state
1126 .pending_pings
1127 .iter()
1128 .position(|p| p.nonce == nonce && p.peer == from);
1129 if let Some(idx) = idx {
1130 let ping = state.pending_pings.swap_remove(idx);
1131 let rtt_ms = now_ms.saturating_sub(ping.sent_at_ms);
1132 let route_hints = packet.trace_route_hops().collect::<Vec<_>>();
1133 let metadata = PongMetadata {
1134 round_trip_ms: rtt_ms,
1135 hop_count: packet.hop_count(),
1136 route_hints,
1137 rssi_dbm: packet.rssi(),
1138 snr_centibels: packet.snr().map(|snr| snr.as_centibels()),
1139 lqi: packet.lqi().map(core::num::NonZeroU8::get),
1140 };
1141 if let Some(entry) = state.peer_subscriptions.iter_mut().find(|e| e.peer == from) {
1142 entry.pong_handlers.for_each_mut(|h| h(rtt_ms));
1143 }
1144 state.pong_handlers.for_each_mut(|h| h(from, rtt_ms));
1145 state
1146 .pong_metadata_handlers
1147 .for_each_mut(|handler| handler(from, &metadata));
1148 }
1149 }
1150
1151 pub(crate) fn expire_pings(&self, now_ms: u64) {
1153 let mut state = self.state.borrow_mut();
1154 let mut i = 0;
1155 while i < state.pending_pings.len() {
1156 if now_ms >= state.pending_pings[i].deadline_ms {
1157 let ping = state.pending_pings.swap_remove(i);
1158 if let Some(entry) = state
1159 .peer_subscriptions
1160 .iter_mut()
1161 .find(|e| e.peer == ping.peer)
1162 {
1163 entry.ping_timeout_handlers.for_each_mut(|h| h());
1164 }
1165 state.ping_timeout_handlers.for_each_mut(|h| h(ping.peer));
1166 } else {
1167 i += 1;
1168 }
1169 }
1170 }
1171
1172 #[cfg(feature = "software-crypto")]
1173 pub async fn request_pfs(
1174 &self,
1175 peer: &PublicKey,
1176 duration_minutes: u16,
1177 options: &SendOptions,
1178 ) -> Result<SendProgressTicket, NodeError<M>> {
1179 let receipt = self
1180 .state
1181 .borrow_mut()
1182 .pfs
1183 .request_session(&self.mac, self.identity_id, peer, duration_minutes, options)
1184 .await?;
1185 Ok(self.register_ack_send(self.identity_id, receipt))
1186 }
1187
1188 #[cfg(feature = "software-crypto")]
1189 pub async fn end_pfs(
1190 &self,
1191 peer: &PublicKey,
1192 options: &SendOptions,
1193 ) -> Result<(), NodeError<M>> {
1194 let _ = self
1195 .state
1196 .borrow_mut()
1197 .pfs
1198 .end_session(&self.mac, self.identity_id, peer, true, options)
1199 .await?;
1200 Ok(())
1201 }
1202
1203 #[cfg(feature = "software-crypto")]
1204 pub async fn pfs_status(&self, peer: &PublicKey) -> Result<PfsStatus, NodeError<M>> {
1205 let now_ms = self.mac.now_ms().await;
1206 let state = self.state.borrow();
1207 if let Some(session) = state
1208 .pfs
1209 .sessions()
1210 .iter()
1211 .find(|session| session.peer_long_term == *peer)
1212 {
1213 return Ok(match session.state {
1214 PfsState::Requested => PfsStatus::Requested,
1215 PfsState::Active => PfsStatus::Active {
1216 local_ephemeral_id: session.local_ephemeral_id,
1217 peer_ephemeral: session.peer_ephemeral,
1218 expires_ms: session.expires_ms,
1219 },
1220 });
1221 }
1222 if state.pfs.active_route(peer, now_ms).is_some() {
1223 return Ok(PfsStatus::Requested);
1225 }
1226 Ok(PfsStatus::Inactive)
1227 }
1228
1229 #[cfg(feature = "software-crypto")]
1232 pub async fn join(&self, channel: &Channel) -> Result<BoundChannel<M>, NodeError<M>> {
1233 let membership = self.membership.borrow_mut();
1234
1235 if let Some(entry) = membership.channels.iter().find(|e| e.channel == *channel) {
1237 if entry.active {
1238 return Ok(BoundChannel {
1239 node: self.clone(),
1240 channel: entry.channel.clone(),
1241 join_generation: entry.generation,
1242 });
1243 }
1244 }
1245
1246 drop(membership);
1250 self.mac.add_private_channel(channel.key().clone()).await?;
1251 let mut membership = self.membership.borrow_mut();
1252
1253 if let Some(entry) = membership
1254 .channels
1255 .iter_mut()
1256 .find(|e| e.channel == *channel)
1257 {
1258 entry.active = true;
1259 entry.generation = entry.generation.wrapping_add(1);
1260 return Ok(BoundChannel {
1261 node: self.clone(),
1262 channel: entry.channel.clone(),
1263 join_generation: entry.generation,
1264 });
1265 }
1266
1267 let generation = 0;
1268 membership.channels.push(ChannelMembershipEntry {
1269 channel: channel.clone(),
1270 generation,
1271 active: true,
1272 });
1273
1274 Ok(BoundChannel {
1275 node: self.clone(),
1276 channel: channel.clone(),
1277 join_generation: generation,
1278 })
1279 }
1280
1281 #[cfg(feature = "software-crypto")]
1285 pub async fn leave(&self, channel: &Channel) -> Result<(), NodeError<M>> {
1286 {
1287 let mut membership = self.membership.borrow_mut();
1288 let Some(entry) = membership
1289 .channels
1290 .iter_mut()
1291 .find(|e| e.channel == *channel && e.active)
1292 else {
1293 return Ok(());
1294 };
1295 entry.active = false;
1296 entry.generation = entry.generation.wrapping_add(1);
1297 }
1298 self.mac.remove_channel(channel.key()).await;
1299 Ok(())
1300 }
1301
1302 #[cfg(feature = "software-crypto")]
1304 pub fn bound_channel(&self, channel: &Channel) -> Option<BoundChannel<M>> {
1305 let membership = self.membership.borrow();
1306 membership
1307 .channels
1308 .iter()
1309 .find(|e| e.channel == *channel && e.active)
1310 .map(|entry| BoundChannel {
1311 node: self.clone(),
1312 channel: entry.channel.clone(),
1313 join_generation: entry.generation,
1314 })
1315 }
1316
1317 #[cfg(feature = "software-crypto")]
1319 pub fn bound_channels(&self) -> Vec<BoundChannel<M>> {
1320 let membership = self.membership.borrow();
1321 membership
1322 .channels
1323 .iter()
1324 .filter(|e| e.active)
1325 .map(|entry| BoundChannel {
1326 node: self.clone(),
1327 channel: entry.channel.clone(),
1328 join_generation: entry.generation,
1329 })
1330 .collect()
1331 }
1332
1333 fn register_ack_send(
1335 &self,
1336 send_identity_id: LocalIdentityId,
1337 receipt: Option<umsh_mac::SendReceipt>,
1338 ) -> SendProgressTicket {
1339 match receipt {
1340 Some(receipt) => {
1341 let token = SendToken::new(send_identity_id, receipt);
1342 let state = self.dispatcher.borrow_mut().register_ticket(token, false);
1343 SendProgressTicket::new(token, state)
1344 }
1345 None => SendProgressTicket::fire_and_forget(),
1347 }
1348 }
1349
1350 fn register_non_ack_send(
1355 &self,
1356 send_identity_id: LocalIdentityId,
1357 receipt: umsh_mac::SendReceipt,
1358 ) -> SendProgressTicket {
1359 let token = SendToken::new(send_identity_id, receipt);
1360 let state = self.dispatcher.borrow_mut().register_ticket(token, true);
1361 SendProgressTicket::new(token, state)
1362 }
1363
1364 pub(crate) fn state(&self) -> &Rc<RefCell<LocalNodeState>> {
1365 &self.state
1366 }
1367
1368 #[cfg(feature = "software-crypto")]
1369 pub(crate) fn owns_ephemeral_identity(&self, identity_id: LocalIdentityId) -> bool {
1370 self.state
1371 .borrow()
1372 .pfs
1373 .sessions()
1374 .iter()
1375 .any(|session| session.local_ephemeral_id == identity_id)
1376 }
1377
1378 #[cfg(feature = "software-crypto")]
1379 pub(crate) async fn handle_pfs_command(
1380 &self,
1381 from: &PublicKey,
1382 channel: Option<ChannelId>,
1383 command: &OwnedMacCommand,
1384 options: &SendOptions,
1385 ) -> Result<Option<PfsLifecycle>, NodeError<M>> {
1386 match *command {
1387 OwnedMacCommand::PfsSessionRequest {
1388 ephemeral_key,
1389 duration_minutes,
1390 } => {
1391 self.state
1392 .borrow_mut()
1393 .pfs
1394 .accept_request(
1395 &self.mac,
1396 self.identity_id,
1397 *from,
1398 ephemeral_key,
1399 duration_minutes,
1400 channel,
1401 options,
1402 )
1403 .await?;
1404 Ok(Some(PfsLifecycle::Established(*from)))
1405 }
1406 OwnedMacCommand::PfsSessionResponse {
1407 ephemeral_key,
1408 duration_minutes,
1409 } => {
1410 if self
1411 .state
1412 .borrow_mut()
1413 .pfs
1414 .accept_response(
1415 &self.mac,
1416 self.identity_id,
1417 *from,
1418 ephemeral_key,
1419 duration_minutes,
1420 )
1421 .await?
1422 {
1423 Ok(Some(PfsLifecycle::Established(*from)))
1424 } else {
1425 Ok(None)
1426 }
1427 }
1428 OwnedMacCommand::EndPfsSession => {
1429 let _ = self
1430 .state
1431 .borrow_mut()
1432 .pfs
1433 .end_session(&self.mac, self.identity_id, from, false, options)
1434 .await?;
1435 Ok(Some(PfsLifecycle::Ended(*from)))
1436 }
1437 _ => Ok(None),
1438 }
1439 }
1440
1441 pub(crate) fn dispatch_received_packet(&self, packet: &ReceivedPacketRef<'_>) -> bool {
1442 let peer = packet.from_key();
1443 let mut state = self.state.borrow_mut();
1444
1445 if let Some(peer) = peer.map(|peer| canonical_peer(&state, peer)) {
1446 if let Some(entry) = state
1447 .peer_subscriptions
1448 .iter_mut()
1449 .find(|entry| entry.peer == peer)
1450 {
1451 if entry.receive_handlers.any_mut(|handler| handler(packet)) {
1452 return true;
1453 }
1454 }
1455 }
1456
1457 state.receive_handlers.any_mut(|handler| handler(packet))
1458 }
1459
1460 pub(crate) fn dispatch_node_discovered(&self, key: PublicKey, name: Option<&str>) {
1461 self.state
1462 .borrow_mut()
1463 .node_discovered_handlers
1464 .for_each_mut(|handler| handler(key, name));
1465 }
1466
1467 pub(crate) fn dispatch_beacon(&self, from_hint: NodeHint, from_key: Option<PublicKey>) {
1468 self.state
1469 .borrow_mut()
1470 .beacon_handlers
1471 .for_each_mut(|handler| handler(from_hint, from_key));
1472 }
1473
1474 pub(crate) fn dispatch_mac_command(&self, from: PublicKey, command: &OwnedMacCommand) {
1475 self.state
1476 .borrow_mut()
1477 .mac_command_handlers
1478 .for_each_mut(|handler| handler(from, command));
1479 }
1480
1481 pub(crate) fn dispatch_transmitted(&self, wire_bytes: &[u8]) {
1482 self.state
1483 .borrow_mut()
1484 .transmitted_handlers
1485 .for_each_mut(|handler| handler(wire_bytes));
1486 }
1487
1488 pub(crate) fn dispatch_ack_received(&self, peer: PublicKey, token: SendToken) {
1489 let mut state = self.state.borrow_mut();
1490 let peer = canonical_peer(&state, peer);
1491 if let Some(entry) = state
1492 .peer_subscriptions
1493 .iter_mut()
1494 .find(|entry| entry.peer == peer)
1495 {
1496 entry
1497 .ack_received_handlers
1498 .for_each_mut(|handler| handler(token));
1499 }
1500 state
1501 .ack_received_handlers
1502 .for_each_mut(|handler| handler(peer, token));
1503 }
1504
1505 pub(crate) fn dispatch_ack_timeout(&self, peer: PublicKey, token: SendToken) {
1506 let mut state = self.state.borrow_mut();
1507 let peer = canonical_peer(&state, peer);
1508 if let Some(entry) = state
1509 .peer_subscriptions
1510 .iter_mut()
1511 .find(|entry| entry.peer == peer)
1512 {
1513 entry
1514 .ack_timeout_handlers
1515 .for_each_mut(|handler| handler(token));
1516 }
1517 state
1518 .ack_timeout_handlers
1519 .for_each_mut(|handler| handler(peer, token));
1520 }
1521
1522 pub(crate) fn dispatch_pfs_established(&self, peer: PublicKey) {
1523 let mut state = self.state.borrow_mut();
1524 let peer = canonical_peer(&state, peer);
1525 if let Some(entry) = state
1526 .peer_subscriptions
1527 .iter_mut()
1528 .find(|entry| entry.peer == peer)
1529 {
1530 entry
1531 .pfs_established_handlers
1532 .for_each_mut(|handler| handler());
1533 }
1534 state
1535 .pfs_established_handlers
1536 .for_each_mut(|handler| handler(peer));
1537 }
1538
1539 pub(crate) fn dispatch_pfs_ended(&self, peer: PublicKey) {
1540 let mut state = self.state.borrow_mut();
1541 let peer = canonical_peer(&state, peer);
1542 if let Some(entry) = state
1543 .peer_subscriptions
1544 .iter_mut()
1545 .find(|entry| entry.peer == peer)
1546 {
1547 entry.pfs_ended_handlers.for_each_mut(|handler| handler());
1548 }
1549 state
1550 .pfs_ended_handlers
1551 .for_each_mut(|handler| handler(peer));
1552 }
1553
1554 pub(crate) fn dispatch_pfs_failed(&self, peer: PublicKey, reason: PfsFailure) {
1555 let mut state = self.state.borrow_mut();
1556 let peer = canonical_peer(&state, peer);
1557 state
1558 .pfs_failed_handlers
1559 .for_each_mut(|handler| handler(peer, reason));
1560 }
1561
1562 pub(crate) async fn expire_pfs_sessions(&self) -> Result<Vec<PublicKey>, NodeError<M>> {
1563 #[cfg(feature = "software-crypto")]
1564 {
1565 let now_ms = self.mac.now_ms().await;
1566 return self
1567 .state
1568 .borrow_mut()
1569 .pfs
1570 .expire_sessions(&self.mac, now_ms)
1571 .await;
1572 }
1573 #[cfg(not(feature = "software-crypto"))]
1574 {
1575 Ok(Vec::new())
1576 }
1577 }
1578
1579 #[cfg(feature = "software-crypto")]
1582 pub(crate) fn expire_pfs_requests(&self, now_ms: u64) -> Vec<PublicKey> {
1583 self.state.borrow_mut().pfs.expire_requests(now_ms)
1584 }
1585}
1586
1587fn canonical_peer(state: &LocalNodeState, peer: PublicKey) -> PublicKey {
1588 #[cfg(feature = "software-crypto")]
1589 {
1590 if let Some(session) = state
1591 .pfs
1592 .sessions()
1593 .iter()
1594 .find(|session| session.state == PfsState::Active && session.peer_ephemeral == peer)
1595 {
1596 return session.peer_long_term;
1597 }
1598 }
1599 peer
1600}
1601
1602impl<M: MacBackend> crate::transport::sealed::Sealed for LocalNode<M> {}
1603
1604impl<M: MacBackend> crate::transport::NodeAccess for LocalNode<M> {
1605 type Backend = M;
1606
1607 fn local_node(&self) -> &LocalNode<M> {
1608 self
1609 }
1610}
1611
1612impl<M: MacBackend> Transport for LocalNode<M> {
1613 type Error = NodeError<M>;
1614
1615 async fn send(
1616 &self,
1617 to: &PublicKey,
1618 payload: &[u8],
1619 options: &SendOptions,
1620 ) -> Result<SendProgressTicket, Self::Error> {
1621 #[cfg(feature = "software-crypto")]
1622 let (send_identity_id, receipt) = {
1623 let now_ms = self.mac.now_ms().await;
1624 if let Some((local_id, peer_ephemeral)) =
1625 self.state.borrow().pfs.active_route(to, now_ms)
1626 {
1627 let receipt = self
1628 .mac
1629 .send_unicast(local_id, &peer_ephemeral, payload, options)
1630 .await?;
1631 (local_id, receipt)
1632 } else {
1633 let receipt = self
1634 .mac
1635 .send_unicast(self.identity_id, to, payload, options)
1636 .await?;
1637 (self.identity_id, receipt)
1638 }
1639 };
1640 #[cfg(not(feature = "software-crypto"))]
1641 let (send_identity_id, receipt) = (
1642 self.identity_id,
1643 self.mac
1644 .send_unicast(self.identity_id, to, payload, options)
1645 .await?,
1646 );
1647 Ok(self.register_ack_send(send_identity_id, receipt))
1648 }
1649
1650 async fn send_all(
1651 &self,
1652 payload: &[u8],
1653 options: &SendOptions,
1654 ) -> Result<SendProgressTicket, Self::Error> {
1655 let receipt = self
1656 .mac
1657 .send_broadcast(self.identity_id, payload, options)
1658 .await?;
1659 Ok(self.register_non_ack_send(self.identity_id, receipt))
1660 }
1661}
1662
1663#[cfg(feature = "software-crypto")]
1669#[derive(Clone)]
1670pub struct BoundChannel<M: MacBackend> {
1671 node: LocalNode<M>,
1672 channel: Channel,
1673 join_generation: u64,
1674}
1675
1676#[cfg(feature = "software-crypto")]
1677impl<M: MacBackend> BoundChannel<M> {
1678 pub fn channel(&self) -> &Channel {
1680 &self.channel
1681 }
1682
1683 pub fn is_active(&self) -> bool {
1685 let membership = self.node.membership.borrow();
1686 membership
1687 .channels
1688 .iter()
1689 .any(|e| e.channel == self.channel && e.active && e.generation == self.join_generation)
1690 }
1691
1692 pub fn peer(&self, key: PublicKey) -> PeerConnection<Self> {
1694 PeerConnection::new(self.clone(), key)
1695 }
1696
1697 fn check_active(&self) -> Result<(), NodeError<M>> {
1699 if self.is_active() {
1700 Ok(())
1701 } else {
1702 Err(NodeError::ChannelLeft)
1703 }
1704 }
1705
1706 pub fn node(&self) -> &LocalNode<M> {
1708 &self.node
1709 }
1710}
1711
1712#[cfg(feature = "software-crypto")]
1713impl<M: MacBackend> crate::transport::sealed::Sealed for BoundChannel<M> {}
1714
1715#[cfg(feature = "software-crypto")]
1716impl<M: MacBackend> crate::transport::NodeAccess for BoundChannel<M> {
1717 type Backend = M;
1718
1719 fn local_node(&self) -> &LocalNode<M> {
1720 &self.node
1721 }
1722}
1723
1724#[cfg(feature = "software-crypto")]
1725impl<M: MacBackend> Transport for BoundChannel<M> {
1726 type Error = NodeError<M>;
1727
1728 async fn send(
1729 &self,
1730 to: &PublicKey,
1731 payload: &[u8],
1732 options: &SendOptions,
1733 ) -> Result<SendProgressTicket, Self::Error> {
1734 self.check_active()?;
1735 let receipt = self
1736 .node
1737 .mac
1738 .send_blind_unicast(
1739 self.node.identity_id,
1740 to,
1741 self.channel.channel_id(),
1742 payload,
1743 options,
1744 )
1745 .await?;
1746 Ok(self.node.register_ack_send(self.node.identity_id, receipt))
1747 }
1748
1749 async fn send_all(
1750 &self,
1751 payload: &[u8],
1752 options: &SendOptions,
1753 ) -> Result<SendProgressTicket, Self::Error> {
1754 self.check_active()?;
1755 let receipt = self
1756 .node
1757 .mac
1758 .send_multicast(
1759 self.node.identity_id,
1760 self.channel.channel_id(),
1761 payload,
1762 options,
1763 )
1764 .await?;
1765 Ok(self
1766 .node
1767 .register_non_ack_send(self.node.identity_id, receipt))
1768 }
1769}