wireguard_conf/models/
builders.rs

1use either::Either;
2use ipnet::Ipv4Net;
3
4use crate::prelude::*;
5
6/// Builder, that used for creating [`Interface`]s.
7///
8/// # Examples
9///
10/// ```
11/// use wireguard_conf::prelude::*;
12///
13/// let server_private_key = PrivateKey::random();
14///
15/// let interface = InterfaceBuilder::new()
16///     .address("10.0.0.1/24".parse().unwrap())
17///     .listen_port(6969)
18///     .private_key(server_private_key.clone())
19///     .set_dns(vec!["8.8.8.8".to_string(), "8.8.4.4".to_string()])
20///     .endpoint("vpn.example.com".to_string())
21///     // .add_peer(some_peer)
22///     .build();
23///
24/// assert_eq!(interface.address, "10.0.0.1/24".parse().unwrap());
25/// assert_eq!(interface.listen_port, Some(6969));
26/// assert_eq!(interface.private_key, server_private_key);
27/// assert_eq!(interface.dns, vec!["8.8.8.8", "8.8.4.4"]);
28/// assert_eq!(interface.endpoint, Some("vpn.example.com".to_string()));
29/// ```
30#[must_use]
31#[derive(Default)]
32pub struct InterfaceBuilder {
33    address: Ipv4Net,
34    listen_port: Option<u16>,
35    private_key: Option<PrivateKey>,
36    dns: Vec<String>,
37    endpoint: Option<String>,
38    peers: Vec<Peer>,
39}
40
41impl InterfaceBuilder {
42    pub fn new() -> InterfaceBuilder {
43        InterfaceBuilder::default()
44    }
45
46    /// Set the address.
47    ///
48    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#address)
49    pub fn address(mut self, address: Ipv4Net) -> Self {
50        self.address = address;
51        self
52    }
53
54    /// Set the listen port.
55    ///
56    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#listenport)
57    pub fn listen_port(mut self, listen_port: u16) -> Self {
58        self.listen_port = Some(listen_port);
59        self
60    }
61
62    /// Set the private key.
63    ///
64    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#privatekey)
65    pub fn private_key(mut self, private_key: PrivateKey) -> Self {
66        self.private_key = Some(private_key);
67        self
68    }
69
70    /// Set the DNS servers array.
71    ///
72    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#dns-2)
73    pub fn set_dns(mut self, dns: Vec<String>) -> Self {
74        self.dns = dns;
75        self
76    }
77
78    /// Add DNS server.
79    ///
80    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#dns-2)
81    pub fn add_dns(mut self, dns: String) -> Self {
82        self.dns.push(dns);
83        self
84    }
85
86    /// Set the endpoint.
87    ///
88    /// # Note
89    ///
90    /// - In interface's config this set `# Name = ...`
91    /// - If you export interface via [`Interface::as_peer()`], exported peer will have this
92    ///   `Peer.endpoint`
93    ///
94    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#listenport)
95    pub fn endpoint(mut self, endpoint: String) -> Self {
96        self.endpoint = Some(endpoint);
97        self
98    }
99
100    /// Set the Peers array.
101    ///
102    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#peer)
103    pub fn set_peers(mut self, peers: Vec<Peer>) -> Self {
104        self.peers = peers;
105        self
106    }
107
108    /// Add peer.
109    ///
110    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#peer)
111    pub fn add_peer(mut self, peer: Peer) -> Self {
112        self.peers.push(peer);
113        self
114    }
115
116    /// Creates [`Interface`].
117    pub fn build(self) -> Interface {
118        Interface {
119            address: self.address,
120            listen_port: self.listen_port,
121            private_key: self.private_key.unwrap_or_else(PrivateKey::random),
122            dns: self.dns,
123
124            // TODO: do amnezia support
125            // amnezia_settings: None,
126
127            endpoint: self.endpoint,
128            peers: self.peers,
129        }
130    }
131}
132
133/// Builder, that used for creating [`Peer`]s.
134///
135/// # Examples
136///
137/// ```
138/// use wireguard_conf::prelude::*;
139/// use either::Either;
140///
141/// let client_private_key = PrivateKey::random();
142///
143/// let peer = PeerBuilder::new()
144///     .endpoint("public.client.example.com".to_string())
145///     .add_allowed_ip("10.0.0.2/32".parse().unwrap())
146///     .private_key(client_private_key.clone())
147///     // if you don't want to generate interface from peer, you can provide public key
148///     // instead of private_key:
149///     //  .public_key(client_public_key)
150///     .build();
151///
152/// assert_eq!(peer.endpoint, Some("public.client.example.com".to_string()));
153/// assert_eq!(peer.allowed_ips, vec!["10.0.0.2/32".parse().unwrap()]);
154/// assert_eq!(peer.key, Either::Left(client_private_key));
155/// ```
156#[must_use]
157#[derive(Default)]
158pub struct PeerBuilder {
159    endpoint: Option<String>,
160    allowed_ips: Vec<Ipv4Net>,
161    key: Option<Either<PrivateKey, PublicKey>>,
162}
163
164impl PeerBuilder {
165    pub fn new() -> PeerBuilder {
166        PeerBuilder::default()
167    }
168
169    /// Sets endpoint.
170    ///
171    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#endpoint)
172    pub fn endpoint(mut self, endpoint: String) -> PeerBuilder {
173        self.endpoint = Some(endpoint);
174        self
175    }
176
177    /// Sets Allowed IPs array.
178    ///
179    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#allowedips)
180    pub fn set_allowed_ips(mut self, ip: Vec<Ipv4Net>) -> PeerBuilder {
181        self.allowed_ips = ip;
182        self
183    }
184
185    /// Adds allowed IP.
186    ///
187    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#allowedips)
188    pub fn add_allowed_ip(mut self, ip: Ipv4Net) -> PeerBuilder {
189        self.allowed_ips.push(ip);
190        self
191    }
192
193    /// Sets private key.
194    ///
195    /// # Note
196    ///
197    /// If you set private key (instead of public key), you can generate [`Interface`] from [`Peer`] (see [`Peer::as_interface()`]).
198    ///
199    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#publickey)
200    pub fn private_key(mut self, private_key: PrivateKey) -> PeerBuilder {
201        self.key = Some(Either::Left(private_key));
202        self
203    }
204
205    /// Sets public key.
206    ///
207    /// [Wireguard Docs](https://github.com/pirate/wireguard-docs?tab=readme-ov-file#publickey)
208    pub fn public_key(mut self, public_key: PublicKey) -> PeerBuilder {
209        self.key = Some(Either::Right(public_key));
210        self
211    }
212
213    /// Creates [`Peer`].
214    pub fn build(self) -> Peer {
215        let key = self
216            .key
217            .unwrap_or_else(|| Either::Left(PrivateKey::random()));
218
219        Peer {
220            endpoint: self.endpoint,
221            allowed_ips: self.allowed_ips,
222            key,
223        }
224    }
225}