diff --git a/server/datahandler.js b/server/datahandler.js index eac6735..9e320ab 100644 --- a/server/datahandler.js +++ b/server/datahandler.js @@ -139,6 +139,7 @@ const callbacks = { dataToSend.rt1 = decode_unicode(rt); dataToSend.rt1_errors = decode_errors(rt); } + dataToSend.rt_flag = flag; }, 'callback_rt*'), ptyn: koffi.register((rds, flag) => ( @@ -222,6 +223,7 @@ var dataToSend = { af: [], rt0: '', rt1: '', + rt_flag: '', ims: 0, eq: 0, ant: 0, @@ -431,15 +433,19 @@ function handleData(wss, receivedData, rdsWss) { } // Serialport retry code when port is open but communication is lost (additional code in index.js) -isSerialportAlive = true; -lastFrequencyAlive = '87.500'; +let state = { + isSerialportAlive: true, + isSerialportRetrying: false, + lastFrequencyAlive: '87.500' +}; + setInterval(() => { - lastFrequencyAlive = initialData.freq; + state.lastFrequencyAlive = initialData.freq; const serialportElapsedTime = process.hrtime(serialportUpdateTime)[0]; // Activate serialport retry if handleData has not been executed for over 8 seconds - if (checkSerialport && (serialportElapsedTime > 8) && !isSerialportRetrying && serverConfig.xdrd.wirelessConnection === false) { - isSerialportAlive = false; - isSerialportRetrying = true; + if (checkSerialport && (serialportElapsedTime > 8) && !state.isSerialportRetrying && serverConfig.xdrd.wirelessConnection === false) { + state.isSerialportAlive = false; + state.isSerialportRetrying = true; } }, 2000); @@ -464,7 +470,13 @@ function showOnlineUsers(currentUsers) { initialData.users = currentUsers; } +let prevFreq = initialData.freq || '87.500'; function processSignal(receivedData, st, stForced) { + if (initialData.freq !== prevFreq) { + prevFreq = initialData.freq; + dataToSend.ps_errors = ''; + } + const modifiedData = receivedData.substring(2); const parsedValue = parseFloat(modifiedData); dataToSend.st = st; @@ -490,5 +502,5 @@ function processSignal(receivedData, st, stForced) { } module.exports = { - handleData, showOnlineUsers, dataToSend, initialData, resetToDefault + handleData, showOnlineUsers, dataToSend, initialData, resetToDefault, state }; diff --git a/server/index.js b/server/index.js index 16ac695..6fd0f3a 100644 --- a/server/index.js +++ b/server/index.js @@ -18,7 +18,7 @@ const path = require('path'); const net = require('net'); const client = new net.Socket(); const { SerialPort } = require('serialport'); -const tunnel = require('./tunnel') +const tunnel = require('./tunnel'); // File imports const helpers = require('./helpers'); @@ -118,12 +118,12 @@ connectToSerial(); tunnel.connect(); // Serialport retry code when port is open but communication is lost (additional code in datahandler.js) -isSerialportRetrying = false; +dataHandler.state.isSerialportRetrying = false; setInterval(() => { - if (!isSerialportAlive && serverConfig.xdrd.wirelessConnection === false) { - isSerialportAlive = true; - isSerialportRetrying = true; + if (!dataHandler.state.isSerialportAlive && serverConfig.xdrd.wirelessConnection === false) { + dataHandler.state.isSerialportAlive = true; + dataHandler.state.isSerialportRetrying = true; if (serialport && serialport.isOpen) { logWarn('Communication lost from ' + serverConfig.xdrd.comPort + ', force closing serialport.'); setTimeout(() => { @@ -163,7 +163,7 @@ if (serverConfig.xdrd.wirelessConnection === false) { } logInfo('Using COM device: ' + serverConfig.xdrd.comPort); - isSerialportAlive = true; + dataHandler.state.isSerialportAlive = true; setTimeout(() => { serialport.write('x\n'); }, 3000); @@ -177,12 +177,12 @@ if (serverConfig.xdrd.wirelessConnection === false) { serialport.write('T' + Math.round(serverConfig.defaultFreq * 1000) + '\n'); dataHandler.initialData.freq = Number(serverConfig.defaultFreq).toFixed(3); dataHandler.dataToSend.freq = Number(serverConfig.defaultFreq).toFixed(3); - } else if (lastFrequencyAlive && isSerialportRetrying) { // Serialport retry code when port is open but communication is lost - serialport.write('T' + (lastFrequencyAlive * 1000) + '\n'); + } else if (dataHandler.state.lastFrequencyAlive && dataHandler.state.isSerialportRetrying) { // Serialport retry code when port is open but communication is lost + serialport.write('T' + (dataHandler.state.lastFrequencyAlive * 1000) + '\n'); } else { serialport.write('T87500\n'); } - isSerialportRetrying = false; + dataHandler.state.isSerialportRetrying = false; serialport.write('A0\n'); serialport.write('F-1\n'); @@ -207,7 +207,7 @@ if (serverConfig.xdrd.wirelessConnection === false) { serialport.on('close', () => { logWarn('Disconnected from ' + serverConfig.xdrd.comPort + '. Attempting to reconnect.'); setTimeout(() => { - isSerialportRetrying = true; + dataHandler.state.isSerialportRetrying = true; connectToSerial(); }, 5000); }); @@ -421,10 +421,12 @@ wss.on('connection', (ws, request) => { ws.on('message', (message) => { const command = helpers.antispamProtection(message, clientIp, ws, userCommands, lastWarn, userCommandHistory, '18', 'text'); - if (((command.startsWith('X') || command.startsWith('Y')) && !request.session.isAdminAuthenticated) || - ((command.startsWith('F') || command.startsWith('W')) && serverConfig.bwSwitch === false)) { - logWarn(`User \x1b[90m${clientIp}\x1b[0m attempted to send a potentially dangerous command. You may consider blocking this user.`); - return; + if (!clientIp.includes("127.0.0.1")) { + if (((command.startsWith('X') || command.startsWith('Y')) && !request.session.isAdminAuthenticated) || + ((command.startsWith('F') || command.startsWith('W')) && serverConfig.bwSwitch === false)) { + logWarn(`User \x1b[90m${clientIp}\x1b[0m attempted to send a potentially dangerous command: ${command.slice(0, 64)}.`); + return; + } } if (command.includes("\'")) { @@ -680,6 +682,26 @@ pluginsWss.on('connection', (ws, request) => { }); }); +function isPortOpen(host, port, timeout = 1000) { + return new Promise((resolve) => { + const socket = new net.Socket(); + + const onError = () => { + socket.destroy(); + resolve(false); + }; + + socket.setTimeout(timeout); + socket.once('error', onError); + socket.once('timeout', onError); + + socket.connect(port, host, () => { + socket.end(); + resolve(true); + }); + }); +} + // Websocket register for /text, /audio and /chat paths httpServer.on('upgrade', (request, socket, head) => { if (request.url === '/text') { @@ -689,8 +711,15 @@ httpServer.on('upgrade', (request, socket, head) => { }); }); } else if (request.url === '/audio') { - proxy.ws(request, socket, head); - } else if (request.url === '/chat') { + isPortOpen('localhost', (Number(serverConfig.webserver.webserverPort) + 10)).then((open) => { + if (open) { + proxy.ws(request, socket, head); + } else { + logWarn(`Audio stream port ${(Number(serverConfig.webserver.webserverPort) + 10)} not yet open — skipping proxy connection.`); + socket.end(); // close socket so client isn't left hanging + } + }); +} else if (request.url === '/chat') { sessionMiddleware(request, {}, () => { chatWss.handleUpgrade(request, socket, head, (ws) => { chatWss.emit('connection', ws, request);