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 = (nm::ProtocolName, DefAddr)> + '_ {
93            self.inbound
94                .iter()
95                .map(|d| (d.proto.clone(), d.addr.clone()))
96        }
97
98        pub(crate) fn multinode_outbound(
99            &self,
100        ) -> impl Iterator<Item = (nm::ProtocolName, DefAddr)> + '_ {
101            self.outbound
102                .iter()
103                .map(|d| (d.proto.clone(), d.addr.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        proto: nm::ProtocolName,
116        addr:  DefAddr,
117    }
118
119    #[cfg(feature = "multinode")]
120    #[derive(Debug, Clone, serde::Deserialize)]
121    pub(super) struct DefMultinodeOutbound {
122        proto: nm::ProtocolName,
123        addr:  DefAddr,
124    }
125
126    impl std::fmt::Display for DefAddr {
127        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128            match self {
129                Self::Tcp(tcp) => write!(f, "tcp://{}", tcp),
130                Self::Uds(uds) => write!(f, "uds://{:?}", uds),
131            }
132        }
133    }
134
135    impl std::str::FromStr for DefAddr {
136        type Err = AnyError;
137
138        fn from_str(s: &str) -> Result<Self, Self::Err> {
139            let url: Url = s.parse().wrap_err("Url::from_str")?;
140            match url.scheme() {
141                "uds" => {
142                    let s = format!(
143                        "{}{}",
144                        url.host().map(|d| d.to_string()).unwrap_or_default(),
145                        url.path()
146                    );
147                    let p: &Path = Path::new(s.as_str());
148                    Ok(Self::Uds(p.into()))
149                },
150                "tcp" => {
151                    let ip: IpAddr = url
152                        .host()
153                        .ok_or(eyre::format_err!("url.host must be present"))?
154                        .to_string()
155                        .parse()
156                        .wrap_err("IpAddr::parse")?;
157                    let port: u16 = url
158                        .port()
159                        .ok_or(eyre::format_err!("url.port must be present"))?;
160                    let socket_addr = SocketAddr::new(ip, port);
161                    Ok(Self::Tcp(socket_addr))
162                },
163                unsupported => Err(eyre::format_err!("unsupported url-scheme: {}", unsupported)),
164            }
165        }
166    }
167
168    impl<'de> Deserialize<'de> for DefAddr {
169        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
170        where
171            D: serde::Deserializer<'de>,
172        {
173            use serde::de::Error as _;
174            String::deserialize(deserializer)?
175                .parse()
176                .map_err(D::Error::custom)
177        }
178    }
179}
180
181mod defaults;