From 6e2787d792de64c003eff03b62a2df798ef851c0 Mon Sep 17 00:00:00 2001 From: salmonik Date: Thu, 29 Oct 2026 20:43:09 +0100 Subject: v2.3.0: add crash with local multiplier and pushed crash event --- src/bin/server/handler.rs | 55 ++++++++++++++++++++++++++++++++++------------- src/bin/server/tls.rs | 9 ++++++++ 2 files changed, 49 insertions(+), 15 deletions(-) (limited to 'src/bin/server') diff --git a/src/bin/server/handler.rs b/src/bin/server/handler.rs index 86b09cb..dffae69 100644 --- a/src/bin/server/handler.rs +++ b/src/bin/server/handler.rs @@ -1,6 +1,11 @@ +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(), @@ -19,34 +24,54 @@ pub fn handle_client_tls(mut stream: TlsStream) { } }; + 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}"); - loop { + 'connection: loop { let mut line = String::new(); match stream.read_line(&mut line) { Ok(0) => break, - Ok(_) => {} + 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; } } - let line = line.trim(); - if line.is_empty() { - continue; - } - - 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; + 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}"); } - let user = state.user().unwrap_or("guest"); - println!("[{user} @ {client_addr}] Sent: {response}"); } core.disconnect(&state); diff --git a/src/bin/server/tls.rs b/src/bin/server/tls.rs index 292ebf7..5d84589 100644 --- a/src/bin/server/tls.rs +++ b/src/bin/server/tls.rs @@ -77,6 +77,15 @@ impl TlsStream { pub fn peer_addr(&self) -> std::io::Result { self.stream.get_ref().peer_addr() } + + /// Read timeout for the socket. The connection loop uses a short one so it + /// can advance crash rounds while no request is in flight. + pub fn set_read_timeout( + &self, + duration: Option, + ) -> std::io::Result<()> { + self.stream.get_ref().set_read_timeout(duration) + } } impl Read for TlsStream { -- cgit v1.2.3