Skip to main content

leodos_protocols/network/
bridge.rs

1//! Bidirectional bridge between a network layer and a
2//! datalink.
3//!
4//! [`Bridge`] forwards packets in both directions: inbound
5//! from the network side to the datalink side, and outbound
6//! from the datalink side to the network side.
7//!
8//! # Example
9//!
10//! ```ignore
11//! let channel = LocalChannel::new();
12//! let (app_handle, router_handle) = channel.split();
13//! let mut bridge = Bridge::new(router, router_handle);
14//! join(app(app_handle), bridge.run()).await;
15//! ```
16
17use futures::FutureExt as _;
18
19use crate::datalink::{DatalinkRead, DatalinkWrite};
20use crate::network::{NetworkRead, NetworkWrite};
21
22/// Bidirectional bridge between a [`NetworkRead`] +
23/// [`NetworkWrite`] and a [`DatalinkRead`] +
24/// [`DatalinkWrite`].
25pub struct Bridge<N, D, const MTU: usize> {
26    network: N,
27    link: D,
28}
29
30impl<N, D, const MTU: usize> Bridge<N, D, MTU> {
31    /// Creates a new bridge.
32    pub fn new(network: N, link: D) -> Self {
33        Self { network, link }
34    }
35}
36
37impl<N, D, const MTU: usize> Bridge<N, D, MTU>
38where
39    N: NetworkRead + NetworkWrite,
40    D: DatalinkRead + DatalinkWrite,
41{
42    /// Runs the bridge loop forever.
43    pub async fn run(&mut self) -> ! {
44        let mut from_net = [0u8; MTU];
45        let mut from_link = [0u8; MTU];
46
47        enum Event {
48            FromNetwork(usize),
49            FromLink(usize),
50            Err,
51        }
52
53        loop {
54            let event = {
55                let net_read =
56                    self.network.read(&mut from_net).fuse();
57                let link_read =
58                    self.link.read(&mut from_link).fuse();
59                pin_utils::pin_mut!(net_read, link_read);
60
61                futures::select_biased! {
62                    r = net_read => match r {
63                        Ok(len) => Event::FromNetwork(len),
64                        Err(_) => Event::Err,
65                    },
66                    r = link_read => match r {
67                        Ok(len) => Event::FromLink(len),
68                        Err(_) => Event::Err,
69                    },
70                }
71            };
72
73            match event {
74                Event::FromNetwork(len) => {
75                    let _ =
76                        self.link.write(&from_net[..len]).await;
77                }
78                Event::FromLink(len) => {
79                    let _ = self
80                        .network
81                        .write(&from_link[..len])
82                        .await;
83                }
84                Event::Err => {}
85            }
86        }
87    }
88}