fix: properly handle disconnects

This commit is contained in:
2025-11-17 11:07:23 -05:00
Unverified
parent 067f2dbf02
commit 8e5bdd373a

View File

@@ -36,6 +36,7 @@ async fn main() -> Result<(), anyhow::Error> {
let clients: Clients = Arc::new(RwLock::new(HashMap::new())); let clients: Clients = Arc::new(RwLock::new(HashMap::new()));
let observers: Observers = Arc::new(RwLock::new(HashMap::new())); let observers: Observers = Arc::new(RwLock::new(HashMap::new()));
let matches: Matches = Arc::new(RwLock::new(HashMap::new())); let matches: Matches = Arc::new(RwLock::new(HashMap::new()));
let admin: Arc<RwLock<Option<SocketAddr>>> = Arc::new(RwLock::new(None));
while let Ok((stream, addr)) = listener.accept().await { while let Ok((stream, addr)) = listener.accept().await {
tokio::spawn(handle_connection( tokio::spawn(handle_connection(
@@ -44,6 +45,7 @@ async fn main() -> Result<(), anyhow::Error> {
clients.clone(), clients.clone(),
observers.clone(), observers.clone(),
matches.clone(), matches.clone(),
admin.clone(),
demo_mode demo_mode
)); ));
} }
@@ -57,6 +59,7 @@ async fn handle_connection(
clients: Clients, clients: Clients,
observers: Observers, observers: Observers,
matches: Matches, matches: Matches,
admin: Arc<RwLock<Option<SocketAddr>>>,
demo_mode: bool, demo_mode: bool,
) -> Result<(), anyhow::Error> { ) -> Result<(), anyhow::Error> {
info!("New WebSocket connection from: {}", addr); info!("New WebSocket connection from: {}", addr);
@@ -69,7 +72,7 @@ async fn handle_connection(
observers.write().await.insert(addr, tx.clone()); observers.write().await.insert(addr, tx.clone());
// Spawn task to handle outgoing messages // Spawn task to handle outgoing messages
let mut send_task = tokio::spawn(async move { let send_task = tokio::spawn(async move {
while let Some(msg) = rx.recv().await { while let Some(msg) = rx.recv().await {
if ws_sender.send(msg).await.is_err() { if ws_sender.send(msg).await.is_err() {
break; break;
@@ -350,11 +353,41 @@ async fn handle_connection(
// Clean up // Clean up
send_task.abort(); send_task.abort();
// TODO: Remove and terminate any matches // Remove and terminate any matches
if let Some(match_id) = clients.read().await.get(&addr).unwrap().read().await.current_match {
let matches_guard = matches.read().await;
let clients_guard = clients.read().await;
let the_match = matches_guard.get(&match_id).unwrap().read().await;
let player1 = clients_guard.get(&the_match.player1).unwrap().read().await;
let player2 = clients_guard.get(&the_match.player2).unwrap().read().await;
let _ = send(&player1.connection, "GAME:TERMINATED");
let _ = send(&player2.connection, "GAME:TERMINATED");
broadcast_message(&the_match.viewers, &observers, "GAME:TERMINATED").await;
drop(player1);
drop(player2);
drop(the_match);
drop(matches_guard);
drop(clients_guard);
matches.write().await.remove(&match_id);
}
clients.write().await.remove(&addr); clients.write().await.remove(&addr);
observers.write().await.remove(&addr);
info!("Client {} removed", addr); let mut admin_guard = admin.write().await;
if let Some(admin_addr) = *admin_guard {
if admin_addr == addr {
*admin_guard = None;
}
}
drop(admin_guard);
info!("Client {} removed", addr);
Ok(()) Ok(())
} }