credence_lib/configuration/port/
port.rs

1use super::{super::error::*, host::*};
2
3use {
4    bytestring::*,
5    compris::resolve::*,
6    kutil_cli::debug::*,
7    kutil_io::network::ip::*,
8    kutil_std::sync::*,
9    std::{io, net::*, path::*, vec},
10};
11
12//
13// Port
14//
15
16/// Port.
17#[derive(Clone, Debug, Debuggable, Resolve)]
18pub struct Port {
19    /// Index.
20    #[debuggable(style(number))]
21    pub index: usize,
22
23    /// Name. Will default to a string representation of the index.
24    #[resolve]
25    #[debuggable(style(string))]
26    pub name: ByteString,
27
28    /// Optional address or hint.
29    ///
30    /// See [ListenableAddressesConfiguration::addresses] where `allow_unspecified` is false.
31    #[resolve]
32    #[debuggable(option, as(display), style(string))]
33    pub address: Option<IpAddr>,
34
35    /// Optional flowinfo for IPv6 address.
36    #[resolve]
37    #[debuggable(option, style(number))]
38    pub flowinfo: Option<u32>,
39
40    /// Optional scope ID for IPv6 address.
41    #[resolve]
42    #[debuggable(option, style(number))]
43    pub scope: Option<u32>,
44
45    /// Whether to include loopbacks when providing reachable addresses.
46    ///
47    /// Default is true.
48    #[resolve(key = "include-loopbacks")]
49    #[debuggable(style(symbol))]
50    pub include_loopbacks: bool,
51
52    /// Hosts.
53    #[resolve]
54    #[debuggable(iter(item), as(debuggable))]
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            flowinfo: None,
68            scope: None,
69            include_loopbacks: true,
70            hosts: Vec::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(port, self.address, self.flowinfo, self.scope, false, self.include_loopbacks)
101    }
102
103    /// To [SocketAddr]s.
104    pub fn socket_addresses(&self, port: u16) -> io::Result<vec::IntoIter<SocketAddr>> {
105        self.listenable_port_configuration(port).to_socket_addrs()
106    }
107}