wireguard_conf/models/
peer.rs

1use either::Either;
2use ipnet::Ipv4Net;
3
4use std::fmt;
5
6use crate::prelude::*;
7
8#[must_use]
9#[derive(Clone, Debug)]
10pub struct Peer {
11    /// Peer's endpoint.
12    pub endpoint: Option<String>,
13
14    /// Peer's allowed IPs.
15    pub allowed_ips: Vec<Ipv4Net>,
16
17    /// Peer's key.
18    ///
19    /// If [`PrivateKey`] is provided, then peer can be exported to interface & full config.
20    /// Otherwise only to peer section of config.
21    pub key: Either<PrivateKey, PublicKey>,
22
23    #[cfg(feature = "amneziawg")]
24    #[cfg_attr(docsrs, doc(cfg(feature = "amneziawg")))]
25    pub amnezia_settings: Option<AmneziaSettings>,
26}
27
28impl Peer {
29    /// Get Peer's [`Interface`].
30    ///
31    /// Pass server's interface to `interface` argument.
32    ///
33    /// # Errors
34    ///
35    /// - [`WireguardError::NoPrivateKeyProvided`] -- peer don't have private key.
36    ///   You need to provide [`PrivateKey`] for creating interfaces from peers.
37    /// - [`WireguardError::NoAssignedIP`] -- no assigned ip found.
38    ///   This means that your peer doesn't have allowed ip, that is in interface's addresses
39    ///   network.
40    pub fn to_interface(&self, interface: &Interface) -> WireguardResult<Interface> {
41        let Either::Left(private_key) = self.key.clone() else {
42            return Err(WireguardError::NoPrivateKeyProvided);
43        };
44
45        let assigned_ip = *self
46            .allowed_ips
47            .iter()
48            .find(|&net| interface.address.contains(net))
49            .ok_or(WireguardError::NoAssignedIP)?;
50
51        Ok(Interface {
52            address: assigned_ip,
53            listen_port: None,
54            private_key,
55            dns: interface.dns.clone(),
56
57            #[cfg(feature = "amneziawg")]
58            amnezia_settings: self.amnezia_settings.clone(),
59
60            endpoint: None,
61            peers: vec![interface.to_peer()],
62        })
63    }
64}
65
66/// Implements [`fmt::Display`] for exporting peer.
67///
68/// # Note
69///
70/// It exports only `[Peer] ...` part. To export full interface, use [`Interface::to_peer()`]
71/// and then [`Peer::to_string()`]
72impl fmt::Display for Peer {
73    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
74        writeln!(f, "[Peer]")?;
75        if let Some(endpoint) = self.endpoint.clone() {
76            writeln!(f, "Endpoint = {endpoint}")?;
77        }
78        writeln!(
79            f,
80            "AllowedIPs = {}",
81            self.allowed_ips
82                .iter()
83                .map(std::string::ToString::to_string)
84                .collect::<Vec<String>>()
85                .join(",")
86        )?;
87        writeln!(
88            f,
89            "PublicKey = {}",
90            self.key.clone().right_or_else(|key| PublicKey::from(&key))
91        )?;
92
93        Ok(())
94    }
95}