// ws-server.js require("dotenv").config(); const WebSocket = require("ws"); const jwt = require("jsonwebtoken"); // ----------------------------------------------------- // CONFIGURAZIONE DA .env // ----------------------------------------------------- const PORT = process.env.WS_PORT || 4002; const HOST = process.env.WS_HOST || "0.0.0.0"; const JWT_SECRET = process.env.JWT_SECRET; if (!JWT_SECRET) { console.error("❌ ERRORE: JWT_SECRET non definito nel .env"); process.exit(1); } // ----------------------------------------------------- // AVVIO WEBSOCKET SERVER // ----------------------------------------------------- const wss = new WebSocket.Server({ port: PORT, host: HOST }); console.log(`🚀 WebSocket server attivo su ws://${HOST}:${PORT}`); // ----------------------------------------------------- // GESTIONE CONNESSIONI // ----------------------------------------------------- wss.on("connection", (ws, req) => { console.log("🔌 Nuovo client connesso"); ws.isAlive = true; ws.on("pong", () => { ws.isAlive = true; }); ws.on("message", msg => { let data; try { data = JSON.parse(msg); } catch (err) { console.error("❌ Errore parsing JSON:", err); return; } // ----------------------------------------------------- // AUTENTICAZIONE JWT // ----------------------------------------------------- if (data.type === "auth") { try { const payload = jwt.verify(data.token, JWT_SECRET); ws.user = payload.name; // es: "Fabio" ws.authenticated = true; ws.send(JSON.stringify({ type: "auth_ok", user: ws.user })); console.log(`🔐 Client autenticato: ${ws.user}`); } catch (err) { ws.send(JSON.stringify({ type: "auth_error", error: err.message })); ws.close(); } return; } // ----------------------------------------------------- // MESSAGGI NON AUTORIZZATI // ----------------------------------------------------- if (!ws.authenticated) { ws.send(JSON.stringify({ type: "error", message: "Not authenticated" })); return; } // ----------------------------------------------------- // MESSAGGI DAL CLIENT (se vuoi gestirli) // ----------------------------------------------------- console.log(`📨 Messaggio da ${ws.user}:`, data); }); ws.on("close", () => { console.log(`❌ Client disconnesso: ${ws.user || "sconosciuto"}`); }); }); // ----------------------------------------------------- // HEARTBEAT (evita connessioni zombie) // ----------------------------------------------------- setInterval(() => { wss.clients.forEach(ws => { if (!ws.isAlive) { console.log(`💀 Connessione zombie terminata: ${ws.user}`); return ws.terminate(); } ws.isAlive = false; ws.ping(); }); }, 30000); // ----------------------------------------------------- // BROADCAST FILTRATO PER UTENTE // ----------------------------------------------------- wss.broadcastToUser = function (user, msg) { const json = JSON.stringify(msg); for (const client of wss.clients) { if ( client.readyState === WebSocket.OPEN && client.authenticated && client.user === user ) { client.send(json); } } }; module.exports = wss;