- Added environment variable configuration for enabling TLS in the WebSocket server. - Implemented logic to read TLS key, certificate, and optional CA paths from environment variables. - Enhanced server initialization to handle both secure (WSS) and non-secure (WS) connections based on the TLS setting. - Included error handling for missing TLS configuration to prevent server startup failures.
122 lines
3.5 KiB
JavaScript
122 lines
3.5 KiB
JavaScript
import WebSocket, { WebSocketServer } from 'ws';
|
|
import https from 'https';
|
|
import fs from 'fs';
|
|
|
|
const PORT = Number.parseInt(process.env.DAEMON_PORT || '4551', 10);
|
|
const USE_TLS = process.env.DAEMON_TLS === '1';
|
|
const TLS_KEY_PATH = process.env.DAEMON_TLS_KEY_PATH;
|
|
const TLS_CERT_PATH = process.env.DAEMON_TLS_CERT_PATH;
|
|
const TLS_CA_PATH = process.env.DAEMON_TLS_CA_PATH; // optional
|
|
|
|
// Einfache In-Memory-Struktur für Verbindungen (für spätere Erweiterungen)
|
|
const connections = new Set();
|
|
|
|
function createServer() {
|
|
let wss;
|
|
|
|
if (USE_TLS) {
|
|
if (!TLS_KEY_PATH || !TLS_CERT_PATH) {
|
|
console.error('[Daemon] DAEMON_TLS=1 gesetzt, aber DAEMON_TLS_KEY_PATH/DAEMON_TLS_CERT_PATH fehlen.');
|
|
process.exit(1);
|
|
}
|
|
const httpsServer = https.createServer({
|
|
key: fs.readFileSync(TLS_KEY_PATH),
|
|
cert: fs.readFileSync(TLS_CERT_PATH),
|
|
ca: TLS_CA_PATH ? fs.readFileSync(TLS_CA_PATH) : undefined,
|
|
});
|
|
wss = new WebSocketServer({ server: httpsServer });
|
|
httpsServer.listen(PORT, '0.0.0.0', () => {
|
|
console.log(`[Daemon] WSS (TLS) Server gestartet auf Port ${PORT}`);
|
|
});
|
|
} else {
|
|
wss = new WebSocketServer({ port: PORT });
|
|
console.log(`[Daemon] WS (ohne TLS) Server startet auf Port ${PORT} ...`);
|
|
}
|
|
|
|
wss.on('connection', (ws, req) => {
|
|
const peer = req.socket.remoteAddress + ':' + req.socket.remotePort;
|
|
ws.isAlive = true;
|
|
ws.userId = null;
|
|
connections.add(ws);
|
|
|
|
console.log(`[Daemon] Neue Verbindung von ${peer}`);
|
|
|
|
ws.on('message', (message) => {
|
|
try {
|
|
if (message.toString() === 'pong') {
|
|
// Client-Pong für unser Ping
|
|
ws.isAlive = true;
|
|
return;
|
|
}
|
|
|
|
const data = JSON.parse(message.toString());
|
|
|
|
// Vom Frontend gesendet nach Verbindungsaufbau
|
|
if (data.event === 'setUserId' && data.data?.userId) {
|
|
ws.userId = data.data.userId;
|
|
console.log(`[Daemon] setUserId erhalten: ${ws.userId}`);
|
|
return;
|
|
}
|
|
|
|
// Admin-Dialog: WebSocket-Log anfordern
|
|
if (data.event === 'getWebsocketLog') {
|
|
const response = {
|
|
event: 'getWebsocketLogResponse',
|
|
entries: [] // aktuell keine Log-Historie implementiert
|
|
};
|
|
ws.send(JSON.stringify(response));
|
|
return;
|
|
}
|
|
|
|
// Platzhalter für spätere Events
|
|
// console.log('[Daemon] Unbekanntes Event:', data);
|
|
} catch (err) {
|
|
console.error('[Daemon] Fehler beim Verarbeiten einer Nachricht:', err);
|
|
}
|
|
});
|
|
|
|
ws.on('close', () => {
|
|
connections.delete(ws);
|
|
console.log('[Daemon] Verbindung geschlossen');
|
|
});
|
|
|
|
ws.on('error', (err) => {
|
|
console.error('[Daemon] WebSocket-Fehler (Verbindung):', err);
|
|
});
|
|
});
|
|
|
|
// Einfache Ping/Pong-Mechanik, damit Verbindungen sauber erkannt werden
|
|
const interval = setInterval(() => {
|
|
for (const ws of connections) {
|
|
if (ws.isAlive === false) {
|
|
console.log('[Daemon] Verbindung wegen fehlendem Pong beendet');
|
|
ws.terminate();
|
|
connections.delete(ws);
|
|
continue;
|
|
}
|
|
ws.isAlive = false;
|
|
try {
|
|
ws.send('ping');
|
|
} catch (err) {
|
|
console.error('[Daemon] Fehler beim Senden von Ping:', err);
|
|
}
|
|
}
|
|
}, 30000);
|
|
|
|
wss.on('close', () => {
|
|
clearInterval(interval);
|
|
connections.clear();
|
|
console.log('[Daemon] Server gestoppt');
|
|
});
|
|
|
|
wss.on('error', (err) => {
|
|
console.error('[Daemon] Server-Fehler:', err);
|
|
});
|
|
|
|
return wss;
|
|
}
|
|
|
|
createServer();
|
|
|
|
|