prns_config/plan/interface/
mod.rs1mod 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}