Skip to main content

irontide_session_core/
settings_convert.rs

1//! `Settings` → runtime-config conversions (M242).
2//!
3//! These were inherent `impl Settings` methods in `settings.rs`. Since
4//! `Settings` is being extracted to the `irontide-settings` crate, they become
5//! an extension trait implemented for `Settings` here, so existing call sites
6//! (`settings.to_dht_config()` etc.) keep working with one `use` import and the
7//! extracted settings crate stays free of session-only deps (dht/nat/utp/i2p).
8
9use irontide_settings::Settings;
10
11/// Conversions from [`Settings`] to the per-subsystem runtime configs.
12pub trait SettingsConvertExt {
13    /// Build the IPv4 DHT config, merging saved nodes ahead of the defaults.
14    fn to_dht_config(&self) -> irontide_dht::DhtConfig;
15    /// Build the IPv6 DHT config, merging saved nodes ahead of the defaults.
16    fn to_dht_config_v6(&self) -> irontide_dht::DhtConfig;
17    /// Build the NAT (`UPnP` / NAT-PMP) port-mapping config.
18    fn to_nat_config(&self) -> irontide_nat::NatConfig;
19    /// Build the IPv4 uTP socket config bound to `port`.
20    fn to_utp_config(&self, port: u16) -> irontide_utp::UtpConfig;
21    /// Build the IPv6 uTP socket config bound to `port`.
22    fn to_utp_config_v6(&self, port: u16) -> irontide_utp::UtpConfig;
23    /// Build the I2P SAM tunnel config from the I2P-related settings.
24    fn to_sam_tunnel_config(&self) -> crate::i2p::SamTunnelConfig;
25}
26
27impl SettingsConvertExt for Settings {
28    fn to_dht_config(&self) -> irontide_dht::DhtConfig {
29        let default = irontide_dht::DhtConfig::default();
30        let mut bootstrap = self.dht_saved_nodes.clone();
31        bootstrap.extend(default.bootstrap_nodes.iter().cloned());
32        irontide_dht::DhtConfig {
33            bootstrap_nodes: bootstrap,
34            own_id: self.dht_node_id,
35            queries_per_second: self.dht_queries_per_second,
36            query_timeout: std::time::Duration::from_secs(self.dht_query_timeout_secs),
37            enforce_node_id: self.dht_enforce_node_id,
38            restrict_routing_ips: self.dht_restrict_routing_ips,
39            dht_max_items: self.dht_max_items,
40            dht_item_lifetime_secs: self.dht_item_lifetime_secs,
41            state_dir: self.resume_data_dir.clone(),
42            read_only_mode: self.dht_read_only,
43            ..default
44        }
45    }
46
47    fn to_dht_config_v6(&self) -> irontide_dht::DhtConfig {
48        let default = irontide_dht::DhtConfig::default_v6();
49        let mut bootstrap = self.dht_saved_nodes.clone();
50        bootstrap.extend(default.bootstrap_nodes.iter().cloned());
51        irontide_dht::DhtConfig {
52            bootstrap_nodes: bootstrap,
53            queries_per_second: self.dht_queries_per_second,
54            query_timeout: std::time::Duration::from_secs(self.dht_query_timeout_secs),
55            enforce_node_id: self.dht_enforce_node_id,
56            restrict_routing_ips: self.dht_restrict_routing_ips,
57            dht_max_items: self.dht_max_items,
58            dht_item_lifetime_secs: self.dht_item_lifetime_secs,
59            state_dir: self.resume_data_dir.clone(),
60            read_only_mode: self.dht_read_only,
61            ..default
62        }
63    }
64
65    fn to_nat_config(&self) -> irontide_nat::NatConfig {
66        irontide_nat::NatConfig {
67            enable_upnp: self.enable_upnp,
68            enable_natpmp: self.enable_natpmp,
69            upnp_lease_duration: self.upnp_lease_duration,
70            natpmp_lifetime: self.natpmp_lifetime,
71        }
72    }
73
74    fn to_utp_config(&self, port: u16) -> irontide_utp::UtpConfig {
75        irontide_utp::UtpConfig {
76            bind_addr: std::net::SocketAddr::from(([0, 0, 0, 0], port)),
77            max_connections: self.utp_max_connections,
78            dscp: self.peer_dscp,
79        }
80    }
81
82    fn to_utp_config_v6(&self, port: u16) -> irontide_utp::UtpConfig {
83        irontide_utp::UtpConfig {
84            bind_addr: std::net::SocketAddr::from((std::net::Ipv6Addr::UNSPECIFIED, port)),
85            max_connections: self.utp_max_connections,
86            dscp: self.peer_dscp,
87        }
88    }
89
90    fn to_sam_tunnel_config(&self) -> crate::i2p::SamTunnelConfig {
91        crate::i2p::SamTunnelConfig {
92            inbound_quantity: self.i2p_inbound_quantity,
93            outbound_quantity: self.i2p_outbound_quantity,
94            inbound_length: self.i2p_inbound_length,
95            outbound_length: self.i2p_outbound_length,
96        }
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103
104    #[test]
105    fn dht_config_inherits_security_settings() {
106        let s = Settings {
107            dht_enforce_node_id: false,
108            ..Settings::default()
109        };
110        let dht = s.to_dht_config();
111        assert!(!dht.enforce_node_id);
112        assert!(dht.restrict_routing_ips);
113
114        let dht_v6 = s.to_dht_config_v6();
115        assert!(!dht_v6.enforce_node_id);
116        assert!(dht_v6.restrict_routing_ips);
117    }
118
119    #[test]
120    fn utp_config_includes_dscp() {
121        let s = Settings {
122            peer_dscp: 0x0A,
123            ..Settings::default()
124        };
125        let utp = s.to_utp_config(6881);
126        assert_eq!(utp.dscp, 0x0A);
127
128        let utp_v6 = s.to_utp_config_v6(6881);
129        assert_eq!(utp_v6.dscp, 0x0A);
130    }
131}