use std::collections::HashMap;
use std::net::SocketAddr;
use rand_chacha::ChaCha20Rng;
use rand_core::Rng;
use crate::core::{ConnectionId, Timestamp};
#[derive(Debug, Default)]
pub(crate) struct IndexTables {
sessions: HashMap<u32, ConnectionId>,
pendings: HashMap<u32, ConnectionId>,
}
impl IndexTables {
pub(crate) fn mint(&self, rng: &mut ChaCha20Rng) -> u32 {
loop {
let candidate = rng.next_u32();
if candidate != 0
&& !self.sessions.contains_key(&candidate)
&& !self.pendings.contains_key(&candidate)
{
return candidate;
}
}
}
pub(crate) fn insert_pending(&mut self, index: u32, conn: ConnectionId) {
self.pendings.insert(index, conn);
}
pub(crate) fn insert_session(&mut self, index: u32, conn: ConnectionId) {
self.sessions.insert(index, conn);
}
pub(crate) fn pending(&self, index: u32) -> Option<ConnectionId> {
self.pendings.get(&index).copied()
}
pub(crate) fn session(&self, index: u32) -> Option<ConnectionId> {
self.sessions.get(&index).copied()
}
pub(crate) fn remove_pending(&mut self, index: u32) {
self.pendings.remove(&index);
}
pub(crate) fn remove_session(&mut self, index: u32) {
self.sessions.remove(&index);
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum StaticState {
Pending,
Live,
}
#[derive(Debug, Clone)]
pub(crate) struct StaticEntry {
pub(crate) conn: ConnectionId,
pub(crate) state: StaticState,
pub(crate) dialled: Option<SocketAddr>,
pub(crate) replacement_basis: Option<Timestamp>,
pub(crate) guard_exempt: bool,
}
#[derive(Debug, Default)]
pub(crate) struct StaticMap {
entries: HashMap<Vec<u8>, StaticEntry>,
}
impl StaticMap {
pub(crate) fn get(&self, key: &[u8]) -> Option<&StaticEntry> {
self.entries.get(key)
}
pub(crate) fn insert(&mut self, key: Vec<u8>, entry: StaticEntry) {
debug_assert!(
!self.entries.contains_key(&key),
"§16.1: one session per peer static"
);
self.entries.insert(key, entry);
}
pub(crate) fn promote(&mut self, key: &[u8], replacement_basis: Option<Timestamp>) {
if let Some(entry) = self.entries.get_mut(key) {
entry.state = StaticState::Live;
entry.dialled = None;
entry.replacement_basis = replacement_basis;
}
}
pub(crate) fn arm_guard_exemption(&mut self, key: &[u8]) {
if let Some(entry) = self.entries.get_mut(key) {
entry.guard_exempt = true;
}
}
pub(crate) fn remove(&mut self, key: &[u8]) -> Option<StaticEntry> {
self.entries.remove(key)
}
pub(crate) fn remove_by_connection(
&mut self,
conn: ConnectionId,
) -> Option<(Vec<u8>, StaticEntry)> {
let key = self
.entries
.iter()
.find(|(_, e)| e.conn == conn)
.map(|(k, _)| k.clone())?;
let entry = self.entries.remove(&key)?;
Some((key, entry))
}
pub(crate) fn hints(&self) -> impl Iterator<Item = SocketAddr> + '_ {
self.entries.values().filter_map(|e| e.dialled)
}
}