use std::collections::BTreeMap;
use std::fs::File;
use std::io::Read;
use std::sync::{Arc, Mutex, MutexGuard};
use std::time::Instant;
use crate::serve::storage::Failure;
pub use lys_pass::signin::{SignedIn, Started};
pub(super) struct Pending {
pub(super) started: Started,
pub(super) at: u64,
}
pub(super) struct Live {
pub(super) until: u64,
pub(super) state: Arc<Mutex<Session>>,
pub(super) valid: Arc<std::sync::atomic::AtomicBool>,
}
impl Drop for Live {
fn drop(&mut self) {
self.valid
.store(false, std::sync::atomic::Ordering::Release);
}
}
pub(super) struct Session {
pub(super) signed_in: SignedIn,
pub(super) answered: u64,
pub(super) refused: Option<String>,
pub(super) attempted: Option<u64>,
pub(super) refresh_finished: Option<Instant>,
}
#[derive(Default)]
pub(super) struct Sessions {
pub(super) pending: Mutex<BTreeMap<String, Pending>>,
pub(super) live: Mutex<BTreeMap<String, Live>>,
}
pub(super) fn lock<T>(mutex: &Mutex<T>) -> Result<MutexGuard<'_, T>, Failure> {
mutex
.lock()
.map_err(|_| Failure::new("door_poisoned", "the door's sessions were poisoned"))
}
pub(super) fn session_id() -> Result<String, Failure> {
let mut bytes = [0_u8; 32];
File::open("/dev/urandom")
.and_then(|mut source| source.read_exact(&mut bytes))
.map_err(|error| Failure::new("door_random_unavailable", error.to_string()))?;
let mut id = String::with_capacity(64);
for digit in bytes.iter().flat_map(|byte| [byte >> 4, byte & 0x0f]) {
id.extend(char::from_digit(u32::from(digit), 16));
}
Ok(id)
}