tubes/
config.rs

1use std::{net::IpAddr, time::Duration};
2
3use pipenet::Versions;
4
5/// Configure the connection.
6/// See extra features `compression` or `encryption` to enable extra fields.
7///
8/// Config can be interpreted directly from a string, see examples in
9/// [Session](crate::prelude::Session).
10#[derive(Clone, Debug)]
11pub struct Config {
12    /// address the destination where to connect to when connecting,
13    /// or the address to bind to when hosting.
14    pub address: Option<IpAddr>,
15    /// port to connect to when client or to bind to when hosting.
16    pub port: u16,
17    /// Versioning for the protocol.
18    pub versions: Versions,
19    /// How long to wait for a new accepted client that did not confirm its
20    /// session with the protocol. Defaults to 5 secs. While waiting for this
21    /// to time out, new connections are delayed from being accepted.
22    pub accept_timeout: Duration,
23    /// Enable compression (LZ4) implemented in pipenet.
24    #[cfg(feature = "compression")]
25    pub compress: bool,
26    /// If Some() this key is used to enable encryption in pipenet.
27    /// Algo used is ChaCha20Poly1305.
28    /// The key must be at least 32 bytes long.
29    /// When this is None, no encryption is enabled.
30    #[cfg(feature = "encryption")]
31    pub key: Option<Vec<u8>>,
32}
33
34impl From<&str> for Config {
35    fn from(value: &str) -> Self {
36        let mut config = Config::default();
37        let mut colons = value.split(":");
38        config.address = colons.next().and_then(|s| s.parse().ok());
39        let after = colons.next().expect("no port provided");
40        let mut with_options = after.split("+");
41        config.port = with_options
42            .next()
43            .and_then(|s| s.parse().ok())
44            .expect("invalid port");
45        #[cfg(feature = "compression")]
46        if let Some(o) = with_options.next()
47            && o == "C"
48        {
49            config.compress = true;
50        }
51        #[cfg(feature = "encryption")]
52        if let Some(o) = with_options.next() {
53            config.key = Some(o.bytes().collect::<Vec<_>>());
54        }
55        config
56    }
57}
58
59impl Default for Config {
60    fn default() -> Self {
61        Self {
62            address: Default::default(),
63            port: u16::MAX,
64            versions: Versions::default(),
65            accept_timeout: Duration::from_secs(5),
66            #[cfg(feature = "compression")]
67            compress: Default::default(),
68            #[cfg(feature = "encryption")]
69            key: Default::default(),
70        }
71    }
72}
73
74// Secrets need proper zeroizing when dropped.
75#[cfg(feature = "encryption")]
76impl Drop for Config {
77    fn drop(&mut self) {
78        let Some(k) = self.key.as_mut() else {
79            return;
80        };
81        for b in k.iter_mut() {
82            *b = 0;
83        }
84    }
85}