128 lines
3.3 KiB
JavaScript
128 lines
3.3 KiB
JavaScript
// 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;
|