credence_lib/configuration/port/
port.rs

1use super::{super::error::*, host::*};
2
3use {
4    compris::resolve::*,
5    kutil::{
6        cli::depict::*,
7        io::network::ip::*,
8        std::{immutable::*, sync::*},
9    },
10    std::{io, net::*, path::*, vec},
11};
12
13//
14// Port
15//
16
17/// Port.
18#[derive(Clone, Debug, Depict, Resolve)]
19pub struct Port {
20    /// Index.
21    #[depict(style(number))]
22    pub index: usize,
23
24    /// Name. Will default to a string representation of the index.
25    #[resolve]
26    #[depict(style(string))]
27    pub name: ByteString,
28
29    /// Optional address or hint.
30    ///
31    /// See [ListenableAddressesConfiguration::addresses] where `allow_unspecified` is false.
32    #[resolve]
33    #[depict(option, as(display), style(string))]
34    pub address: Option<IpAddr>,
35    /// Optional zone for IPv6 address.
36    #[resolve]
37    #[depict(option, style(string))]
38    pub zone: Option<ByteString>,
39
40    /// Optional flowinfo for IPv6 address.
41    #[resolve]
42    #[depict(option, style(number))]
43    pub flowinfo: Option<u32>,
44
45    /// Whether to include loopbacks when providing reachable addresses.
46    ///
47    /// Default is true.
48    #[resolve(key = "include-loopbacks")]
49    #[depict(style(symbol))]
50    pub include_loopbacks: bool,
51
52    /// Hosts.
53    #[resolve]
54    #[depict(iter(item), as(depict))]
55    pub hosts: Vec<Host>,
56}
57
58static COUNTER: Counter = Counter::new();
59
60impl Default for Port {
61    fn default() -> Self {
62        let index = COUNTER.next();
63        Self {
64            index,
65            name: index.to_string().into(),
66            address: None,
67            zone: None,
68            flowinfo: None,
69            include_loopbacks: true,
70            hosts: Default::default(),
71        }
72    }
73}
74
75impl Port {
76    /// Validate.
77    pub fn validate<PathT>(&mut self, base_path: PathT) -> Result<(), ConfigurationError>
78    where
79        PathT: AsRef<Path>,
80    {
81        let base_path = base_path.as_ref();
82        for host in &mut self.hosts {
83            host.validate(base_path)?;
84        }
85        Ok(())
86    }
87
88    /// Whether any of the hosts has TLS.
89    pub fn is_tls(&self) -> bool {
90        for host in &self.hosts {
91            if host.has_tls() {
92                return true;
93            }
94        }
95        false
96    }
97
98    /// Create a [ListenablePortConfiguration].
99    pub fn listenable_port_configuration(&self, port: u16) -> ListenablePortConfiguration {
100        ListenablePortConfiguration::new(
101            port,
102            self.address,
103            self.zone.clone().map(|zone| zone.into()),
104            self.flowinfo,
105            false,
106            self.include_loopbacks,
107        )
108    }
109
110    /// To [SocketAddr]s.
111    pub fn socket_addresses(&self, port: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
112        self.listenable_port_configuration(port).to_socket_addrs()
113    }
114}