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;