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}