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