ergot_base/interface_manager/profiles/direct_router/
mod.rs

1//! The Direct Router profile
2//!
3//! This is an early and simple router profile that can manage multiple directly connected
4//! edge devices. It can route messages from one directly connected edge device to another,
5//! as well as messages to/from itself and an edge device. It does not currently handle
6//! multi-hop routing.
7
8use log::{debug, trace, warn};
9
10use crate::{
11    Header, ProtocolError,
12    interface_manager::{
13        DeregisterError, Interface, InterfaceSendError, InterfaceState, Profile, SetStateError,
14        profiles::direct_edge::{CENTRAL_NODE_ID, DirectEdge},
15    },
16};
17
18pub mod std_tcp;
19
20#[cfg(feature = "nusb-v0_1")]
21pub mod nusb_0_1;
22
23struct Node<I: Interface> {
24    edge: DirectEdge<I>,
25    net_id: u16,
26    ident: u64,
27}
28
29pub struct DirectRouter<I: Interface> {
30    interface_ctr: u64,
31    nodes: Vec<Node<I>>,
32}
33
34impl<I: Interface> Profile for DirectRouter<I> {
35    type InterfaceIdent = u64;
36
37    fn send<T: serde::Serialize>(
38        &mut self,
39        hdr: &crate::Header,
40        data: &T,
41    ) -> Result<(), InterfaceSendError> {
42        let intfc = self.find(hdr)?;
43        intfc.send(hdr, data)
44    }
45
46    fn send_err(
47        &mut self,
48        hdr: &crate::Header,
49        err: ProtocolError,
50    ) -> Result<(), InterfaceSendError> {
51        let intfc = self.find(hdr)?;
52        intfc.send_err(hdr, err)
53    }
54
55    fn send_raw(
56        &mut self,
57        hdr: &crate::Header,
58        hdr_raw: &[u8],
59        data: &[u8],
60    ) -> Result<(), InterfaceSendError> {
61        let intfc = self.find(hdr)?;
62        intfc.send_raw(hdr, hdr_raw, data)
63    }
64
65    fn interface_state(&mut self, ident: Self::InterfaceIdent) -> Option<InterfaceState> {
66        let node = self.nodes.iter_mut().find(|n| n.ident == ident)?;
67        node.edge.interface_state(())
68    }
69
70    fn set_interface_state(
71        &mut self,
72        ident: Self::InterfaceIdent,
73        state: InterfaceState,
74    ) -> Result<(), SetStateError> {
75        let Some(node) = self.nodes.iter_mut().find(|n| n.ident == ident) else {
76            return Err(SetStateError::InterfaceNotFound);
77        };
78        node.edge.set_interface_state((), state)
79    }
80}
81
82impl<I: Interface> DirectRouter<I> {
83    pub fn new() -> Self {
84        Self {
85            interface_ctr: 0,
86            nodes: vec![],
87        }
88    }
89
90    pub fn get_nets(&mut self) -> Vec<u16> {
91        self.nodes
92            .iter_mut()
93            .filter_map(|n| match n.edge.interface_state(())? {
94                InterfaceState::Down => None,
95                InterfaceState::Inactive => None,
96                InterfaceState::ActiveLocal { .. } => None,
97                InterfaceState::Active { net_id, node_id: _ } => Some(net_id),
98            })
99            .collect()
100    }
101
102    fn find<'b>(&'b mut self, ihdr: &Header) -> Result<&'b mut DirectEdge<I>, InterfaceSendError> {
103        // todo: make this state impossible? enum of dst w/ or w/o key?
104        if ihdr.dst.port_id == 0 && ihdr.any_all.is_none() {
105            return Err(InterfaceSendError::AnyPortMissingKey);
106        }
107
108        let Ok(idx) = self
109            .nodes
110            .binary_search_by_key(&ihdr.dst.network_id, |n| n.net_id)
111        else {
112            return Err(InterfaceSendError::NoRouteToDest);
113        };
114
115        Ok(&mut self.nodes[idx].edge)
116    }
117
118    pub fn register_interface(&mut self, sink: I::Sink) -> Option<u64> {
119        if self.nodes.is_empty() {
120            let net_id = 1;
121            let intfc_id = self.interface_ctr;
122            self.interface_ctr += 1;
123
124            self.nodes.push(Node {
125                edge: DirectEdge::new_controller(
126                    sink,
127                    InterfaceState::Active {
128                        net_id,
129                        node_id: CENTRAL_NODE_ID,
130                    },
131                ),
132                net_id,
133                ident: intfc_id,
134            });
135            debug!("Alloc'd net_id 1");
136            return Some(intfc_id);
137        } else if self.nodes.len() >= 65534 {
138            warn!("Out of netids!");
139            return None;
140        }
141
142        let mut net_id = 1;
143        // we're not empty, find the lowest free address by counting the
144        // indexes, and if we find a discontinuity, allocate the first one.
145        for intfc in self.nodes.iter() {
146            if intfc.net_id > net_id {
147                trace!("Found gap: {net_id}");
148                break;
149            }
150            debug_assert!(intfc.net_id == net_id);
151            net_id += 1;
152        }
153        // EITHER: We've found a gap that we can use, OR we've iterated all
154        // interfaces, which means that we had contiguous allocations but we
155        // have not exhausted the range.
156        debug_assert!(net_id > 0 && net_id != u16::MAX);
157
158        let intfc_id = self.interface_ctr;
159        self.interface_ctr += 1;
160
161        // todo we could probably just insert at (net_id - 1)?
162        self.nodes.push(Node {
163            edge: DirectEdge::new_controller(
164                sink,
165                InterfaceState::Active {
166                    net_id,
167                    node_id: CENTRAL_NODE_ID,
168                },
169            ),
170            net_id,
171            ident: intfc_id,
172        });
173        self.nodes.sort_unstable_by_key(|i| i.net_id);
174        Some(intfc_id)
175    }
176
177    pub fn deregister_interface(&mut self, ident: u64) -> Result<(), DeregisterError> {
178        let Some(pos) = self.nodes.iter().position(|n| n.ident == ident) else {
179            return Err(DeregisterError::NoSuchInterface);
180        };
181        _ = self.nodes.remove(pos);
182        Ok(())
183    }
184}
185
186impl<I: Interface> Default for DirectRouter<I> {
187    fn default() -> Self {
188        Self::new()
189    }
190}