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