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;