use std::net::SocketAddr;
use std::time::Instant;
use crate::core::SyncState;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ServerSessionId([u8; 6]);
impl ServerSessionId {
pub fn new(bytes: [u8; 6]) -> Self {
Self(bytes)
}
pub fn generate() -> Self {
use std::time::{SystemTime, UNIX_EPOCH};
let seed = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos() as u64;
let mut id = [0u8; 6];
let mut state = seed;
for byte in &mut id {
state = state.wrapping_mul(6364136223846793005).wrapping_add(1);
*byte = (state >> 33) as u8;
}
Self(id)
}
pub fn as_bytes(&self) -> &[u8; 6] {
&self.0
}
pub fn to_u64(&self) -> u64 {
let mut buf = [0u8; 8];
buf[..6].copy_from_slice(&self.0);
u64::from_le_bytes(buf)
}
}
impl std::fmt::Display for ServerSessionId {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:012x}", self.to_u64())
}
}
impl From<[u8; 6]> for ServerSessionId {
fn from(bytes: [u8; 6]) -> Self {
Self::new(bytes)
}
}
impl From<ServerSessionId> for [u8; 6] {
fn from(id: ServerSessionId) -> [u8; 6] {
id.0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SessionState {
Handshaking,
Active,
Closing,
Closed,
}
#[derive(Debug)]
pub struct ServerSession<S: SyncState> {
id: ServerSessionId,
client_addr: SocketAddr,
client_public_key: [u8; 32],
state: SessionState,
server_state: S,
client_state_version: u64,
server_state_version: u64,
last_activity: Instant,
created_at: Instant,
extensions: Vec<u16>,
}
impl<S: SyncState> ServerSession<S> {
pub fn new(
id: ServerSessionId,
client_addr: SocketAddr,
client_public_key: [u8; 32],
initial_state: S,
) -> Self {
let now = Instant::now();
Self {
id,
client_addr,
client_public_key,
state: SessionState::Handshaking,
server_state: initial_state,
client_state_version: 0,
server_state_version: 0,
last_activity: now,
created_at: now,
extensions: Vec::new(),
}
}
pub fn id(&self) -> ServerSessionId {
self.id
}
pub fn client_addr(&self) -> SocketAddr {
self.client_addr
}
pub fn client_public_key(&self) -> &[u8; 32] {
&self.client_public_key
}
pub fn state(&self) -> SessionState {
self.state
}
pub fn set_state(&mut self, state: SessionState) {
self.state = state;
}
pub fn server_state(&self) -> &S {
&self.server_state
}
pub fn server_state_mut(&mut self) -> &mut S {
&mut self.server_state
}
pub fn update_server_state(&mut self, state: S) {
self.server_state = state;
self.server_state_version += 1;
}
pub fn client_state_version(&self) -> u64 {
self.client_state_version
}
pub fn update_client_state_version(&mut self, version: u64) {
self.client_state_version = version;
}
pub fn server_state_version(&self) -> u64 {
self.server_state_version
}
pub fn touch(&mut self) {
self.last_activity = Instant::now();
}
pub fn idle_time(&self) -> std::time::Duration {
self.last_activity.elapsed()
}
pub fn age(&self) -> std::time::Duration {
self.created_at.elapsed()
}
pub fn is_active(&self) -> bool {
self.state == SessionState::Active
}
pub fn update_client_addr(&mut self, addr: SocketAddr) {
self.client_addr = addr;
self.touch();
}
pub fn set_extensions(&mut self, extensions: Vec<u16>) {
self.extensions = extensions;
}
pub fn extensions(&self) -> &[u16] {
&self.extensions
}
pub fn compression_enabled(&self) -> bool {
self.extensions.contains(&0x0001)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_session_id_generate() {
let id1 = ServerSessionId::generate();
let id2 = ServerSessionId::generate();
assert_ne!(id1, id2);
}
#[test]
fn test_session_id_display() {
let id = ServerSessionId::new([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
let display = format!("{}", id);
assert_eq!(display.len(), 12); }
}