use std::time::Duration; use crate::tls::TlsStream; use zagan_bet::server::core::{ConnectionState, ServerCore}; /// How long the connection waits for a request before advancing timed games. const POLL_INTERVAL: Duration = Duration::from_millis(50); pub fn handle_client_tls(mut stream: TlsStream) { let client_addr = match stream.peer_addr() { Ok(addr) => addr.to_string(), Err(error) => { eprintln!("Could not get peer address: {error}"); return; } }; let db_path = std::env::var("SERVER_DB").unwrap_or_else(|_| "server.db".to_string()); let mut core = match ServerCore::open(&db_path) { Ok(core) => core, Err(error) => { eprintln!("Failed to open database {db_path}: {error}"); return; } }; if let Err(error) = stream.set_read_timeout(Some(POLL_INTERVAL)) { eprintln!("Could not set read timeout: {error}"); return; } let mut state = ConnectionState::default(); println!("[TLS Client connected] {client_addr}"); 'connection: loop { let mut line = String::new(); match stream.read_line(&mut line) { Ok(0) => break, Ok(_) => { let line = line.trim(); if !line.is_empty() { let user = state.user().unwrap_or("guest").to_string(); println!("[{user} @ {client_addr}] Received: {line}"); let response = core.handle_message(&mut state, line); if let Err(error) = stream.write_line(&response) { eprintln!("Write error: {error}"); break; } let user = state.user().unwrap_or("guest"); println!("[{user} @ {client_addr}] Sent: {response}"); } } Err(error) if matches!( error.kind(), std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut ) => { // No request yet: fall through and let timed games advance. } Err(error) => { eprintln!("Read error: {error}"); break; } } for push in core.poll(&state) { if let Err(error) = stream.write_line(&push) { eprintln!("Write error: {error}"); break 'connection; } let user = state.user().unwrap_or("guest"); println!("[{user} @ {client_addr}] Pushed: {push}"); } } core.disconnect(&state); println!("[TLS Client disconnected] {client_addr}"); }