Skip to main content

ts_control/
derp.rs

1use alloc::collections::BTreeMap;
2
3use ts_derp::TlsValidationConfig;
4
5/// The full derp state, a map of [`ts_derp::RegionId`]s to [`Region`]s.
6pub type Map = BTreeMap<ts_derp::RegionId, Region>;
7
8/// Convert a derp map from the [`ts_control_serde`] representation to the [`ts_derp`]
9/// representation.
10pub fn convert_derp_map(
11    derp_map: &ts_control_serde::DerpMap<'_>,
12) -> impl Iterator<Item = (ts_derp::RegionId, Region)> {
13    derp_map.regions.iter().map(|(id, region)| {
14        let id = ts_derp::RegionId((*id).into());
15        let region: Region = region.into();
16
17        (id, region)
18    })
19}
20
21/// A single derp [`Region`], holding the region info and all the server info.
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct Region {
24    /// The info for this region.
25    pub info: ts_derp::RegionInfo,
26
27    /// Servers in this region.
28    pub servers: Vec<ts_derp::ServerConnInfo>,
29}
30
31impl From<&ts_control_serde::DerpRegion<'_>> for Region {
32    fn from(region: &ts_control_serde::DerpRegion<'_>) -> Self {
33        let info = region_info(region);
34        let servers = region.nodes.iter().map(server).collect();
35
36        Region { info, servers }
37    }
38}
39
40fn region_info(region: &ts_control_serde::DerpRegion) -> ts_derp::RegionInfo {
41    ts_derp::RegionInfo {
42        name: region.name.to_string(),
43        code: region.code.to_string(),
44        no_measure_no_home: region.no_measure_no_home,
45    }
46}
47
48fn server(server: &ts_control_serde::DerpServer) -> ts_derp::ServerConnInfo {
49    const DEFAULT_TLS_PORT: u16 = 443;
50
51    let https_port = match server.derp_port {
52        0 => DEFAULT_TLS_PORT,
53        port => port,
54    };
55
56    #[cfg_attr(not(feature = "insecure-derp"), allow(unused_mut))]
57    let mut tls_config =
58        TlsValidationConfig::from_str(server.cert_name.unwrap_or_default(), &server.hostname);
59
60    #[cfg(feature = "insecure-derp")]
61    if server.insecure_for_tests {
62        tls_config = TlsValidationConfig::InsecureForTests;
63    };
64
65    ts_derp::ServerConnInfo {
66        hostname: server.hostname.to_string(),
67        https_port,
68        stun_port: server.stun_port.into(),
69        supports_port_80: server.can_port_80,
70
71        ipv4: convert_ip_usage(server.ipv4),
72        ipv6: convert_ip_usage(server.ipv6),
73
74        stun_only: server.stun_only,
75
76        tls_validation_config: tls_config,
77    }
78}
79
80fn convert_ip_usage<T>(ip: ts_control_serde::DerpIpUsage<T>) -> ts_derp::IpUsage<T>
81where
82    T: Copy,
83{
84    match ip {
85        ts_control_serde::DerpIpUsage::Disable => ts_derp::IpUsage::Disable,
86        ts_control_serde::DerpIpUsage::UseDns => ts_derp::IpUsage::UseDns,
87        ts_control_serde::DerpIpUsage::FixedAddr(ip) => ts_derp::IpUsage::FixedAddr(ip),
88    }
89}