use rand::prelude::*;
use std::{collections::HashSet, fmt};
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
use serde::{Deserialize, Serialize};
use super::{WireguardError, WireguardResult};
macro_rules! assert_return {
($test:expr, $err:expr) => {
if !($test) {
return Err($err);
}
};
}
#[must_use]
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct AmneziaSettings {
pub jc: usize,
pub jmin: usize,
pub jmax: usize,
pub s1: usize,
pub s2: usize,
pub h1: usize,
pub h2: usize,
pub h3: usize,
pub h4: usize,
}
impl AmneziaSettings {
pub fn random() -> Self {
let mut rng = rand::rng();
let jc = rng.random_range(4..=12);
let jmin = 8;
let jmax = 80;
let s1 = rng.random_range(15..=150);
let s2 = {
let mut value = s1 + 56;
while s1 + 56 == value {
value = rng.random_range(1..=150);
}
value
};
let h1 = rng.random_range(10..=2_147_483_640);
let h2 = rng.random_range(10..=2_147_483_640);
let h3 = rng.random_range(10..=2_147_483_640);
let h4 = rng.random_range(10..=2_147_483_640);
Self {
jc,
jmin,
jmax,
s1,
s2,
h1,
h2,
h3,
h4,
}
}
pub fn validate(&self) -> WireguardResult<()> {
assert_return!(
1 <= self.jc && self.jc <= 128,
WireguardError::InvalidAmneziaSetting("Jc".to_string())
);
assert_return!(
self.jmin < self.jmax,
WireguardError::InvalidAmneziaSetting("Jmin".to_string())
);
assert_return!(
self.jmax <= 1280,
WireguardError::InvalidAmneziaSetting("Jmax".to_string())
);
assert_return!(
self.s1 < 1280 && self.s1 + 56 != self.s2,
WireguardError::InvalidAmneziaSetting("S1".to_string())
);
assert_return!(
self.s2 < 1280,
WireguardError::InvalidAmneziaSetting("S2".to_string())
);
let are_h_values_unique = {
let set = HashSet::from([self.h1, self.h2, self.h3, self.h4]);
set.len() == 4
};
assert_return!(
are_h_values_unique,
WireguardError::InvalidAmneziaSetting("H1/H2/H3/H4".to_string())
);
Ok(())
}
}
impl fmt::Display for AmneziaSettings {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Jc = {}", self.jc)?;
writeln!(f, "Jmin = {}", self.jmin)?;
writeln!(f, "Jmax = {}", self.jmax)?;
writeln!(f, "S1 = {}", self.s1)?;
writeln!(f, "S2 = {}", self.s2)?;
writeln!(f, "H1 = {}", self.h1)?;
writeln!(f, "H2 = {}", self.h2)?;
writeln!(f, "H3 = {}", self.h3)?;
writeln!(f, "H4 = {}", self.h4)?;
Ok(())
}
}