#[cfg(test)]
mod binding_test;
use std::collections::HashMap;
use std::net::SocketAddr;
use tokio::time::Instant;
const MIN_CHANNEL_NUMBER: u16 = 0x4000;
const MAX_CHANNEL_NUMBER: u16 = 0x7fff;
#[derive(Copy, Clone, Debug, PartialEq)]
pub(crate) enum BindingState {
Idle,
Request,
Ready,
Refresh,
Failed,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub(crate) struct Binding {
pub(crate) number: u16,
pub(crate) st: BindingState,
pub(crate) addr: SocketAddr,
pub(crate) refreshed_at: Instant,
}
impl Binding {
pub(crate) fn set_state(&mut self, state: BindingState) {
self.st = state;
}
pub(crate) fn state(&self) -> BindingState {
self.st
}
pub(crate) fn set_refreshed_at(&mut self, at: Instant) {
self.refreshed_at = at;
}
pub(crate) fn refreshed_at(&self) -> Instant {
self.refreshed_at
}
}
#[derive(Default)]
pub(crate) struct BindingManager {
chan_map: HashMap<u16, String>,
addr_map: HashMap<String, Binding>,
next: u16,
}
impl BindingManager {
pub(crate) fn new() -> Self {
BindingManager {
chan_map: HashMap::new(),
addr_map: HashMap::new(),
next: MIN_CHANNEL_NUMBER,
}
}
pub(crate) fn assign_channel_number(&mut self) -> u16 {
let n = self.next;
if self.next == MAX_CHANNEL_NUMBER {
self.next = MIN_CHANNEL_NUMBER;
} else {
self.next += 1;
}
n
}
pub(crate) fn create(&mut self, addr: SocketAddr) -> Option<&Binding> {
let b = Binding {
number: self.assign_channel_number(),
st: BindingState::Idle,
addr,
refreshed_at: Instant::now(),
};
self.chan_map.insert(b.number, b.addr.to_string());
self.addr_map.insert(b.addr.to_string(), b);
self.addr_map.get(&addr.to_string())
}
pub(crate) fn find_by_addr(&self, addr: &SocketAddr) -> Option<&Binding> {
self.addr_map.get(&addr.to_string())
}
pub(crate) fn get_by_addr(&mut self, addr: &SocketAddr) -> Option<&mut Binding> {
self.addr_map.get_mut(&addr.to_string())
}
pub(crate) fn find_by_number(&self, number: u16) -> Option<&Binding> {
let s = self.chan_map.get(&number)?;
self.addr_map.get(s)
}
pub(crate) fn get_by_number(&mut self, number: u16) -> Option<&mut Binding> {
let s = self.chan_map.get(&number)?;
self.addr_map.get_mut(s)
}
pub(crate) fn delete_by_addr(&mut self, addr: &SocketAddr) -> bool {
if let Some(b) = self.addr_map.remove(&addr.to_string()) {
self.chan_map.remove(&b.number);
true
} else {
false
}
}
pub(crate) fn delete_by_number(&mut self, number: u16) -> bool {
if let Some(s) = self.chan_map.remove(&number) {
self.addr_map.remove(&s);
true
} else {
false
}
}
pub(crate) fn size(&self) -> usize {
self.addr_map.len()
}
}