const ws = require('ws'); const URL = require('url'); const { listen } = require('../lib/db/notify'); const channels = require('../lib/db/channels'); const jwt = require('../lib/jwt'); function start (server, pingInterval=30000) { const wsServer = new ws.Server({ noServer: true }); wsServer.on('connection', socket => { socket.alive = true; socket.on('pong', function () { this.alive = true; }) socket.on('message', message => { // console.log("Websocket message:"); // console.log(message); try { const payload = JSON.parse(message); if (payload?.jwt) { jwt.checkValidCredentials({jwt: payload.jwt}).then( decoded => { // console.log("Decoded", decoded); if (decoded) { console.log("Renewing JWT via websocket"); delete decoded.exp; const token = jwt.issue(decoded); socket.send(JSON.stringify({ channel: ".jwt", payload: { token } })); } }); } } catch (err) { console.warn("Websocket message decoding failed", err); } }); }); server.on('upgrade', (request, socket, head) => { // console.log("Received upgrade request", request.url); const url = URL.parse(request.url); if (/^\/ws\/?$/.test(url.pathname)) { wsServer.handleUpgrade(request, socket, head, socket => { wsServer.emit('connection', socket, request); }); } }); listen(channels, (data) => { wsServer.clients.forEach( (socket) => { socket.send(JSON.stringify(data)); }) }); const interval = setInterval( () => { wsServer.clients.forEach( (socket) => { if (!socket.alive) { return socket.terminate(); } socket.alive = false; socket.ping(); }) }, pingInterval); wsServer.on('close', () => clearInterval(interval)); return wsServer; } module.exports = { start }