#[derive(Debug, Clone)]
pub(crate) struct SessionRng {
state: u64,
}
impl SessionRng {
pub(crate) fn from_entropy() -> Self {
let nanos = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_nanos() as u64)
.unwrap_or(0x2545_F491_4F6C_DD1D);
Self::from_seed(nanos ^ (u64::from(std::process::id()) << 32))
}
pub(crate) fn from_seed(seed: u64) -> Self {
Self {
state: if seed == 0 {
0x9E37_79B9_7F4A_7C15
} else {
seed
},
}
}
pub(crate) fn next_u64(&mut self) -> u64 {
let mut x = self.state;
x ^= x >> 12;
x ^= x << 25;
x ^= x >> 27;
self.state = x;
x.wrapping_mul(0x2545_F491_4F6C_DD1D)
}
}
static ROOT_SEED: std::sync::LazyLock<std::sync::Mutex<SessionRng>> =
std::sync::LazyLock::new(|| {
std::sync::Mutex::new(match crate::config::tuning_u64("stealth.seed") {
Some(seed) => SessionRng::from_seed(seed),
None => SessionRng::from_entropy(),
})
});
pub(crate) fn session_rng_fork() -> SessionRng {
let seed = match ROOT_SEED.lock() {
Ok(mut root) => root.next_u64(),
Err(poisoned) => poisoned.into_inner().next_u64(),
};
SessionRng::from_seed(seed)
}