use std::io::{BufRead, BufReader, Write}; use std::net::TcpStream; use std::sync::Mutex; use once_cell::sync::Lazy; use rusqlite::Connection; use crate::database; static DB_CONN: Lazy> = Lazy::new(|| Mutex::new(database::init_db())); pub fn handle_client(stream: TcpStream) { let client_addr = stream.peer_addr().unwrap().to_string(); let mut user = "guest".to_string(); println!("[{} @ {}] Client connected", user, client_addr); let reader_stream = stream.try_clone().unwrap(); let reader = BufReader::new(reader_stream); let mut writer = stream; for line in reader.lines() { let line = line.unwrap(); println!("[{} @ {}] Received: {}", user, client_addr, line); let response = process_message(&line, &mut user); writeln!(writer, "{}", response).unwrap(); } println!("[{} @ {}] Client disconnected", user, client_addr); } fn process_message(msg: &str, user: &mut String) -> String { let parts: Vec<&str> = msg.splitn(3, ' ').collect(); match parts[0] { "REGISTER" => { if parts.len() != 3 { "FAIL Invalid REGISTER format".to_string() } else { let username = parts[1]; let hashed_pass = parts[2]; let db = DB_CONN.lock().unwrap(); match database::add_user(&db, username, hashed_pass) { Ok(_) => format!("OK Registered {}", username), Err(_) => "FAIL User already exists".to_string(), } } } "AUTH" => { if parts.len() != 3 { "FAIL Invalid AUTH format".to_string() } else { let username = parts[1]; let provided_hash = parts[2]; let db = DB_CONN.lock().unwrap(); if let Some(stored_hash) = database::get_hashed_password(&db, username) { if provided_hash == stored_hash { *user = username.to_string(); format!("OK {}", username) } else { "FAIL Invalid credentials".to_string() } } else { "FAIL User not found".to_string() } } } "PING" => "PING".to_string(), _ => msg.to_string(), // Echo back for compatibility } }