mm1_node/
config.rs

1use std::collections::HashMap;
2
3use mm1_address::subnet::NetAddress;
4use tokio::runtime::Runtime;
5
6mod actor_config;
7mod rt_config;
8mod validation;
9
10pub(crate) use actor_config::EffectiveActorConfig;
11pub use validation::{Valid, ValidationError};
12
13use crate::actor_key::ActorKey;
14
15#[derive(Debug, Clone, serde::Deserialize)]
16pub struct Mm1NodeConfig {
17    #[serde(default = "defaults::local_subnets")]
18    local_subnets: Vec<DefLocalSubnet>,
19
20    #[cfg(feature = "multinode")]
21    #[serde(default = "Default::default")]
22    inbound: Vec<DefMultinodeInbound>,
23
24    #[cfg(feature = "multinode")]
25    #[serde(default = "Default::default")]
26    outbound: Vec<DefMultinodeOutbound>,
27
28    #[serde(default)]
29    actor: actor_config::ActorConfigNode,
30
31    #[serde(default)]
32    runtime: rt_config::RtConfigs,
33}
34
35#[derive(Debug, Clone, serde::Deserialize)]
36struct DefLocalSubnet {
37    net:  NetAddress,
38    kind: LocalSubnetKind,
39}
40
41#[derive(Debug, Clone, Copy, serde::Deserialize)]
42#[serde(rename_all = "lowercase")]
43enum LocalSubnetKind {
44    Auto,
45    Bind,
46}
47
48impl Valid<Mm1NodeConfig> {
49    pub(crate) fn actor_config(&self, actor_key: &ActorKey) -> impl EffectiveActorConfig + '_ {
50        self.actor.select(actor_key)
51    }
52
53    pub(crate) fn build_runtimes(&self) -> std::io::Result<(Runtime, HashMap<String, Runtime>)> {
54        self.runtime.build_runtimes()
55    }
56
57    pub(crate) fn local_subnet_address_auto(&self) -> NetAddress {
58        self.local_subnets
59            .iter()
60            .find(|d| matches!(d.kind, LocalSubnetKind::Auto))
61            .expect("exactly one local subnet must be present")
62            .net
63    }
64
65    pub(crate) fn local_subnet_addresses_bind(&self) -> impl Iterator<Item = NetAddress> + '_ {
66        self.local_subnets
67            .iter()
68            .filter_map(|d| matches!(d.kind, LocalSubnetKind::Bind).then_some(d.net))
69    }
70}
71
72#[cfg(feature = "multinode")]
73pub(crate) use multinode::*;
74#[cfg(feature = "multinode")]
75mod multinode {
76
77    use std::net::{IpAddr, SocketAddr};
78    use std::path::Path;
79    use std::{fmt, str};
80
81    use eyre::Context;
82    use mm1_common::types::AnyError;
83    use mm1_proto_network_management as nm;
84    use serde::Deserialize;
85    use url::Url;
86
87    use super::*;
88
89    impl Valid<Mm1NodeConfig> {
90        pub(crate) fn multinode_inbound(
91            &self,
92        ) -> impl Iterator<Item = (Vec<nm::ProtocolName>, DefAddr, nm::Options)> + '_ {
93            self.inbound
94                .iter()
95                .map(|d| (d.proto.clone(), d.addr.clone(), d.options.clone()))
96        }
97
98        pub(crate) fn multinode_outbound(
99            &self,
100        ) -> impl Iterator<Item = (Vec<nm::ProtocolName>, DefAddr, nm::Options)> + '_ {
101            self.outbound
102                .iter()
103                .map(|d| (d.proto.clone(), d.addr.clone(), d.options.clone()))
104        }
105    }
106
107    #[derive(Debug, Clone)]
108    pub(crate) enum DefAddr {
109        Tcp(SocketAddr),
110        Uds(Box<Path>),
111    }
112
113    #[derive(Debug, Clone, serde::Deserialize)]
114    pub(super) struct DefMultinodeInbound {
115        #[serde(default)]
116        proto: Vec<nm::ProtocolName>,
117        addr:  DefAddr,
118
119        #[serde(flatten)]
120        options: nm::Options,
121    }
122
123    #[cfg(feature = "multinode")]
124    #[derive(Debug, Clone, serde::Deserialize)]
125    pub(super) struct DefMultinodeOutbound {
126        #[serde(default)]
127        proto: Vec<nm::ProtocolName>,
128        addr:  DefAddr,
129
130        #[serde(flatten)]
131        options: nm::Options,
132    }
133
134    impl std::fmt::Display for DefAddr {
135        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136            match self {
137                Self::Tcp(tcp) => write!(f, "tcp://{}", tcp),
138                Self::Uds(uds) => write!(f, "uds://{:?}", uds),
139            }
140        }
141    }
142
143    impl std::str::FromStr for DefAddr {
144        type Err = AnyError;
145
146        fn from_str(s: &str) -> Result<Self, Self::Err> {
147            let url: Url = s.parse().wrap_err("Url::from_str")?;
148            match url.scheme() {
149                "uds" => {
150                    let s = format!(
151                        "{}{}",
152                        url.host().map(|d| d.to_string()).unwrap_or_default(),
153                        url.path()
154                    );
155                    let p: &Path = Path::new(s.as_str());
156                    Ok(Self::Uds(p.into()))
157                },
158                "tcp" => {
159                    let ip: IpAddr = url
160                        .host()
161                        .ok_or(eyre::format_err!("url.host must be present"))?
162                        .to_string()
163                        .parse()
164                        .wrap_err("IpAddr::parse")?;
165                    let port: u16 = url
166                        .port()
167                        .ok_or(eyre::format_err!("url.port must be present"))?;
168                    let socket_addr = SocketAddr::new(ip, port);
169                    Ok(Self::Tcp(socket_addr))
170                },
171                unsupported => Err(eyre::format_err!("unsupported url-scheme: {}", unsupported)),
172            }
173        }
174    }
175
176    impl<'de> Deserialize<'de> for DefAddr {
177        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
178        where
179            D: serde::Deserializer<'de>,
180        {
181            use serde::de::Error as _;
182            String::deserialize(deserializer)?
183                .parse()
184                .map_err(D::Error::custom)
185        }
186    }
187}
188
189mod defaults;