Skip to main content

prns_config/plan/interface/
mod.rs

1mod discovery;
2mod medium;
3mod policy;
4
5pub(super) use super::error::PlanErrorKind;
6pub(super) use discovery::plan_interface_discovery;
7pub use discovery::{
8    DiscoveryAdvertisementPlan, DiscoveryAnnouncementPlan, DiscoveryEncryption,
9    DiscoveryIfacPublication, DiscoveryLocationPlan, DiscoveryPublicationProblem,
10    InterfaceDiscoveryPlan,
11};
12pub(super) use medium::{airtime_limit, ready_command_flow_control, station_identification};
13pub use medium::{
14    AddressFamilyPreference, AirtimeLimitCentiPercent, AutoInterfaceDataPort,
15    AutoInterfaceDevicePolicy, AutoInterfaceDiscoveryPort, AutoInterfaceDiscoveryScope,
16    AutoInterfaceGroupId, AutoInterfaceMulticastAddressType, AutoInterfacePlan,
17    ConnectTimeoutSeconds, I2pPeerPlan, I2pPeersPlan, I2pReachabilityPlan, PipeCommandPlan,
18    PipeRespawnDelay, PlannedMedium, ReadyCommandFlowControl, ReconnectLimit, SerialDataBits,
19    SerialLinePlan, SerialParity, SerialStopBits, StationIdentificationPlan, TcpDialPlan,
20    TcpListenHost, TcpListenPlan, TcpTunnelMode, UdpEndpointHost, UdpEndpointPlan, UdpFlowPlan,
21    WebSocketTargetPlan,
22};
23pub(super) use policy::{
24    effective_policy, global_announce_rate, global_common_policy, InheritedInterfacePolicy,
25    MemberEgressPolicy,
26};
27
28#[cfg(test)]
29pub(super) use medium::RNS_DEFAULT_SERIAL_BAUD;
30
31use prns_core::interfaces::IfacSize;
32use prns_core::interfaces::{
33    AnnounceRateLimit, EffectiveInterfacePolicy, InterfaceCommonPolicy, InterfaceGravity,
34};
35
36use self::discovery::plan_interface_discovery as discovery_plan;
37use self::medium::plan_medium;
38use self::policy::effective_policy as plan_effective_policy;
39use crate::reference::keys::interface as interface_key;
40use crate::reference::ReferenceInterface;
41
42#[derive(Debug, Clone, PartialEq)]
43pub struct PlannedInterface {
44    pub name: String,
45    pub policy: EffectiveInterfacePolicy,
46    pub access: InterfaceAccessPlan,
47    pub medium: PlannedMedium,
48    pub discovery: InterfaceDiscoveryPlan,
49    pub lifecycle: ConfiguredInterfaceLifecycle,
50}
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53pub enum ConfiguredInterfaceLifecycle {
54    Persistent,
55    BootstrapOnly,
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub enum InterfaceAccessPlan {
60    Open,
61    Ifac {
62        network_name: Option<String>,
63        passphrase: Option<String>,
64        size: IfacSize,
65    },
66}
67
68pub(super) fn plan_interface(
69    interface: &ReferenceInterface,
70    global_common: InterfaceCommonPolicy,
71    global_announce_rate: Option<AnnounceRateLimit>,
72    default_gravity: InterfaceGravity,
73    transport_enabled: bool,
74) -> Result<PlannedInterface, PlanErrorKind> {
75    let medium = plan_medium(interface)?;
76    let access = plan_access(interface, &medium)?;
77    let discovery = discovery_plan(interface, &medium);
78    let policy = plan_effective_policy(
79        interface,
80        &medium,
81        &discovery,
82        InheritedInterfacePolicy {
83            common: global_common,
84            announce_rate: global_announce_rate,
85            gravity: default_gravity,
86        },
87        transport_enabled,
88        MemberEgressPolicy::Inherit,
89    )?;
90    Ok(PlannedInterface {
91        name: interface.name.clone(),
92        policy,
93        access,
94        medium,
95        discovery,
96        lifecycle: if interface.bootstrap_only == Some(true) {
97            ConfiguredInterfaceLifecycle::BootstrapOnly
98        } else {
99            ConfiguredInterfaceLifecycle::Persistent
100        },
101    })
102}
103
104pub(super) fn plan_access(
105    interface: &ReferenceInterface,
106    medium: &PlannedMedium,
107) -> Result<InterfaceAccessPlan, PlanErrorKind> {
108    if interface.network_name.is_none() && interface.passphrase.is_none() {
109        return Ok(InterfaceAccessPlan::Open);
110    }
111    let default_size = match medium {
112        PlannedMedium::AutoWifi(_)
113        | PlannedMedium::TcpClient { .. }
114        | PlannedMedium::TcpServer { .. }
115        | PlannedMedium::Udp { .. }
116        | PlannedMedium::Backbone { .. }
117        | PlannedMedium::BackboneClient { .. }
118        | PlannedMedium::I2p { .. }
119        | PlannedMedium::Weave { .. }
120        | PlannedMedium::PrnsUsbAuto
121        | PlannedMedium::PrnsWebSocketClient { .. }
122        | PlannedMedium::PrnsWebSocketServer { .. } => IfacSize::WIDE,
123        PlannedMedium::Serial { .. }
124        | PlannedMedium::Kiss { .. }
125        | PlannedMedium::Ax25Kiss { .. }
126        | PlannedMedium::Pipe { .. }
127        | PlannedMedium::Rnode { .. }
128        | PlannedMedium::RnodeMulti { .. }
129        | PlannedMedium::PrnsBluetoothAuto => IfacSize::NARROW,
130    };
131    let size = match interface.ifac_size_bits {
132        Some(bits) if bits >= 8 => {
133            IfacSize::new((bits / 8) as usize).map_err(|_| PlanErrorKind::InvalidSetting {
134                key: interface_key::IFAC_SIZE,
135            })?
136        }
137        Some(_) | None => default_size,
138    };
139    Ok(InterfaceAccessPlan::Ifac {
140        network_name: interface.network_name.clone(),
141        passphrase: interface.passphrase.clone(),
142        size,
143    })
144}