ratman_configure/
config.rs

1//!
2
3use async_std::task::block_on;
4use ratman::Router;
5use std::collections::BTreeMap;
6use std::{net::SocketAddr, ops::Deref, sync::Arc};
7
8pub type Id = usize;
9
10/// A wrapper type for parameters that are required for an endpoint
11#[derive(Clone, Debug)]
12pub enum Params {
13    /// Virtual testing endpoint purely in memory
14    ///
15    /// Because it is only used to connect with one other endpoint in
16    /// memory no parameters are required to make a network of virtual
17    /// endpoints work.
18    Virtual,
19    /// Internet tcp overlay endpoint
20    ///
21    /// To initialise this module requires a bind address, and a port.
22    /// Optionally a `dynamic` flag can be passed along which will set
23    /// up the endpoint to accept new peers introduced dynamically.
24    Tcp {
25        addr: String,
26        port: u16,
27        peers: Vec<String>,
28        dynamic: bool,
29    },
30    /// Purely local udp broadcast endpoint
31    ///
32    /// Because of how multicast works on Linux, all udp modules in a
33    /// network need to be running on the same port.  This means that
34    /// two udp endpoints can't be running on the same computer at the
35    /// same time for testing purposes, without network namespaces.
36    LocalUpd { addr: String },
37    /// Android wifi direct support
38    #[cfg(feature = "android")]
39    WifiDirect,
40}
41
42/// Configuration for a single endpoint
43#[derive(Clone, Debug)]
44pub struct Endpoint {
45    /// A unique ID for this endpoint
46    pub id: usize,
47    /// Type and required parameter set for initialisation
48    pub params: Params,
49}
50
51/// A network endpoint patch type
52///
53/// When creating internal test networks (running inside the same
54/// daemon, but communicating via different endpoint backends, you can
55/// chose the "internal" option to patch them together.  This means
56/// manually introducing Tcp endpoints to each other, or simply
57/// hooking up the internal memory channel of `netmod-mem`.
58///
59/// Use the `External` type to use the endpoint to configure against
60/// an external target (meaning actual network traffic).
61#[derive(Clone, Debug)]
62pub enum Patch {
63    Internal(Id),
64    External,
65}
66
67/// A set of endpoints to connect to various networks
68///
69/// The list of endpoints defines
70#[derive(Clone, Debug, Default)]
71pub struct Network {
72    /// Set of endpoints for this network backend
73    pub endpoints: BTreeMap<Id, Endpoint>,
74    /// Manual internal patch configuration
75    pub patches: BTreeMap<Id, Patch>,
76}
77
78impl Network {
79    pub fn new() -> Self {
80        Self::default()
81    }
82
83    /// Consume the `Network` instance to initialise a Router
84    pub fn into_router(self) -> Arc<Router> {
85        let _p = self.patches;
86
87        self.endpoints
88            .into_iter()
89            .fold(Router::new(), |router, (_, ep)| {
90                match ep.params {
91                    // FIXME: Figure out what the udp module actually needs
92                    Params::LocalUpd { addr: _ } => {
93                        use netmod_udp::Endpoint;
94                        let ep = Endpoint::spawn(9000);
95                        block_on(async { router.add_endpoint(ep).await });
96                    }
97                    Params::Tcp {
98                        addr,
99                        port,
100                        peers,
101                        dynamic,
102                    } => {
103                        use netmod_tcp::{Endpoint, Mode};
104                        block_on(async {
105                            let ep = Endpoint::new(
106                                &addr,
107                                port,
108                                "qauld",
109                                if dynamic { Mode::Dynamic } else { Mode::Static },
110                            )
111                            .await
112                            .unwrap();
113                            ep.add_peers(peers).await.unwrap();
114                            router.add_endpoint(ep).await;
115                        });
116                    }
117                    _ => unimplemented!(),
118                }
119
120                router
121            })
122    }
123}
124
125impl Deref for Network {
126    type Target = BTreeMap<usize, Endpoint>;
127    fn deref(&self) -> &Self::Target {
128        &self.endpoints
129    }
130}