diff --git a/.gitignore b/.gitignore index be66cb2..6e750dd 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ features/redis_conf.rb config/redis.json *~ +node_modules/ +environment.json \ No newline at end of file diff --git a/broadcaster/package.json b/broadcaster/package.json index 3d0b417..f15b05f 100644 --- a/broadcaster/package.json +++ b/broadcaster/package.json @@ -1,9 +1,9 @@ { "name": "broadcaster", "version": "1.0.0", + "type": "module", "dependencies": { - "socket.io": "0.9.17", - "hiredis": "", - "redis": "" + "redis": "^4.5.1", + "socket.io": "0.9.19" } } diff --git a/broadcaster/pnpm-lock.yaml b/broadcaster/pnpm-lock.yaml new file mode 100644 index 0000000..91fb746 --- /dev/null +++ b/broadcaster/pnpm-lock.yaml @@ -0,0 +1,186 @@ +lockfileVersion: 5.4 + +specifiers: + redis: ^4.5.1 + socket.io: 0.9.19 + +dependencies: + redis: 4.5.1 + socket.io: 0.9.19 + +packages: + + /@redis/bloom/1.1.0_@redis+client@1.4.2: + resolution: {integrity: sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.4.2 + dev: false + + /@redis/client/1.4.2: + resolution: {integrity: sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==} + engines: {node: '>=14'} + dependencies: + cluster-key-slot: 1.1.1 + generic-pool: 3.9.0 + yallist: 4.0.0 + dev: false + + /@redis/graph/1.1.0_@redis+client@1.4.2: + resolution: {integrity: sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.4.2 + dev: false + + /@redis/json/1.0.4_@redis+client@1.4.2: + resolution: {integrity: sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.4.2 + dev: false + + /@redis/search/1.1.0_@redis+client@1.4.2: + resolution: {integrity: sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.4.2 + dev: false + + /@redis/time-series/1.0.4_@redis+client@1.4.2: + resolution: {integrity: sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==} + peerDependencies: + '@redis/client': ^1.0.0 + dependencies: + '@redis/client': 1.4.2 + dev: false + + /active-x-obfuscator/0.0.1: + resolution: {integrity: sha512-8gdEZinfLSCfAUulETDth4ZSIDPSchiPgm5PLrXQC6BANf1YFEDrPPM2MdK2zcekMROwtM667QFuYw/H6ZV06Q==} + dependencies: + zeparser: 0.0.5 + dev: false + + /base64id/0.1.0: + resolution: {integrity: sha512-DSjtfjhAsHl9J4OJj7e4+toV2zqxJrGwVd3CLlsCp8QmicvOn7irG0Mb8brOc/nur3SdO8lIbNlY1s1ZDJdUKQ==} + engines: {node: '>= 0.4.0'} + dev: false + + /cluster-key-slot/1.1.1: + resolution: {integrity: sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==} + engines: {node: '>=0.10.0'} + dev: false + + /commander/2.1.0: + resolution: {integrity: sha512-J2wnb6TKniXNOtoHS8TSrG9IOQluPrsmyAJ8oCUJOBmv+uLBCyPYAZkD2jFvw2DCzIXNnISIM01NIvr35TkBMQ==} + engines: {node: '>= 0.6.x'} + dev: false + + /generic-pool/3.9.0: + resolution: {integrity: sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==} + engines: {node: '>= 4'} + dev: false + + /nan/1.0.0: + resolution: {integrity: sha512-Wm2/nFOm2y9HtJfgOLnctGbfvF23FcQZeyUZqDD8JQG3zO5kXh3MkQKiUaA68mJiVWrOzLFkAV1u6bC8P52DJA==} + dev: false + + /options/0.0.6: + resolution: {integrity: sha512-bOj3L1ypm++N+n7CEbbe473A414AB7z+amKYshRb//iuL3MpdDCLhPnw6aVTdKB9g5ZRVHIEp8eUln6L2NUStg==} + engines: {node: '>=0.4.0'} + dev: false + + /policyfile/0.0.4: + resolution: {integrity: sha512-UfDtlscNialXfmVEwEPm0t/5qtM0xPK025eYWd/ilv89hxLIhVQmt3QIzMHincLO2MBtZyww0386pt13J4aIhQ==} + dev: false + + /redis/0.7.3: + resolution: {integrity: sha512-0Pgb0jOLfn6eREtEIRn/ifyZJjl2H+wUY4F/Pe7T4UhmoSrZ/1HU5ZqiBpDk8I8Wbyv2N5DpXKzbEtMj3drprg==} + requiresBuild: true + dev: false + optional: true + + /redis/4.5.1: + resolution: {integrity: sha512-oxXSoIqMJCQVBTfxP6BNTCtDMyh9G6Vi5wjdPdV/sRKkufyZslDqCScSGcOr6XGR/reAWZefz7E4leM31RgdBA==} + dependencies: + '@redis/bloom': 1.1.0_@redis+client@1.4.2 + '@redis/client': 1.4.2 + '@redis/graph': 1.1.0_@redis+client@1.4.2 + '@redis/json': 1.0.4_@redis+client@1.4.2 + '@redis/search': 1.1.0_@redis+client@1.4.2 + '@redis/time-series': 1.0.4_@redis+client@1.4.2 + dev: false + + /socket.io-client/0.9.16: + resolution: {integrity: sha512-wSM7PKJkzpGqUAo6d6SAn+ph4xeQJ6nzyDULRJAX1G7e6Xm0wNuMh2RpNvwXrHMzoV9Or5hti7LINiQAm1H2yA==} + engines: {node: '>= 0.4.0'} + dependencies: + active-x-obfuscator: 0.0.1 + uglify-js: 1.2.5 + ws: 0.4.32 + xmlhttprequest: 1.4.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /socket.io/0.9.19: + resolution: {integrity: sha512-UPdVIGPBPmCibzIP2rAjXuiPTI2gPs6kiu4P7njH6WAK7wiOlozNG62ohohCNOycx+Dztd4vRNXxq8alIOEtfA==} + engines: {node: '>= 0.4.0'} + dependencies: + base64id: 0.1.0 + policyfile: 0.0.4 + socket.io-client: 0.9.16 + optionalDependencies: + redis: 0.7.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /tinycolor/0.0.1: + resolution: {integrity: sha512-+CorETse1kl98xg0WAzii8DTT4ABF4R3nquhrkIbVGcw1T8JYs5Gfx9xEfGINPUZGDj9C4BmOtuKeaTtuuRolg==} + engines: {node: '>=0.4.0'} + dev: false + + /uglify-js/1.2.5: + resolution: {integrity: sha512-Ps1oQryKOcRDYuAN1tGpPWd/DIRMcdLz4p7JMxLjJiFvp+aaG01IEu0ZSoVvYUSxIkvW7k2X50BCW2InguEGlg==} + hasBin: true + dev: false + + /ws/0.4.32: + resolution: {integrity: sha512-htqsS0U9Z9lb3ITjidQkRvkLdVhQePrMeu475yEfOWkAYvJ6dSjQp1tOH6ugaddzX5b7sQjMPNtY71eTzrV/kA==} + engines: {node: '>=0.4.0'} + hasBin: true + requiresBuild: true + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dependencies: + commander: 2.1.0 + nan: 1.0.0 + options: 0.0.6 + tinycolor: 0.0.1 + dev: false + + /xmlhttprequest/1.4.2: + resolution: {integrity: sha512-WTsthd44hTdCRrHkdtTgbgTKIJyNDV+xiShdooFZBUstY7xk+EXMx/u5gjuUXaCiCWvtBVCHwauzml2joevB4w==} + engines: {node: '>=0.4.0'} + dev: false + + /yallist/4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: false + + /zeparser/0.0.5: + resolution: {integrity: sha512-Qj4lJIRPy7hIW1zCBqwA3AW8F9uHswVoXPnotuY6uyNgbg5qGb6SJfWZi+YzD3DktbUnUoGiGZFhopbn9l1GYw==} + dev: false diff --git a/broadcaster/server.js b/broadcaster/server.js index 6a6c0a2..5fe4641 100644 --- a/broadcaster/server.js +++ b/broadcaster/server.js @@ -1,80 +1,67 @@ -if (process.argv.length != 3) { - console.error("Specify the path of the environment.json file please!"); - console.error("Usage: node server.js environment.json"); - process.exit(2); -} +import io from 'socket.io'; +import redis from 'redis'; -var fs = require('fs'); -var env = JSON.parse(fs.readFileSync(process.argv[2])); +import { createServer } from 'http'; +import { readFileSync } from 'fs'; -var trackerConfig = env['tracker_config']; +import HTTPPolling from 'socket.io/lib/transports/http-polling.js'; +import XHRPolling from 'socket.io/lib/transports/xhr-polling.js'; -var app = require('http').createServer(httpHandler), - io = require('socket.io').listen(app), - redis = require('redis').createClient(Number(env['redis_port'] || 6379), - env['redis_host'] || '127.0.0.1', - Number(env['redis_db'] || 0)), - numberOfClients = 0, - recentMessages = {}; +const httpHandler = async (request, response) => { + let m; + let output; -app.listen(8080); - -redis.on("error", function (err) { - console.log("Error " + err); -}); - -redis.on("message", redisHandler); - -function httpHandler(request, response) { - var m; if (m = request.url.match(/^\/recent\/(.+)/)) { - var channel = m[1]; - response.writeHead(200, {"Content-Type": "text/plain; charset=UTF-8", - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Credentials': 'true'}); + let channel = m[1]; + response.writeHead(200, { + "Content-Type": "text/plain; charset=UTF-8", + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Credentials': 'true' + }); output = JSON.stringify(recentMessages[channel] || []); - response.end(output); } else { response.writeHead(200, {"Content-Type": "text/plain"}); output = "" + numberOfClients; - response.end(output); } + + response.end(output); } -function redisHandler(pubsubChannel, message) { - console.log(message); - var msgParsed = JSON.parse(message); - console.log(msgParsed); - var channel = msgParsed['log_channel']; - if (!recentMessages[channel]) { - recentMessages[channel] = []; - } - var msgList = recentMessages[channel]; - msgList.push(msgParsed); - while (msgList.length > 20) { - msgList.shift(); - } - io.of('/'+channel).emit('log_message', message); +if (process.argv.length != 3) { + console.error("Specify the path of the environment.json file please!"); + console.error("Usage: node server.js environment.json"); + process.exit(2); +} + +const env = JSON.parse(readFileSync(process.argv[2])), + trackerConfig = env['tracker_config']; + +const app = createServer(httpHandler), + ioApp = io.listen(app), + redisClient = redis.createClient(Number(env['redis_port'] || 6379), + env['redis_host'] || '127.0.0.1', + Number(env['redis_db'] || 0)), + recentMessages = {}; + +await redisClient.connect(); +if (env['redis_password']) { + await redisClient.auth(env['redis_password']); } +var numberOfClients = 0; -io.configure(function() { - io.set("transports", ["websocket", "xhr-polling"]); - io.set("polling duration", 10); +app.listen(8080); - var path = require('path'); - var HTTPPolling = require(path.join( - path.dirname(require.resolve('socket.io')),'lib', 'transports','http-polling') - ); - var XHRPolling = require(path.join( - path.dirname(require.resolve('socket.io')),'lib','transports','xhr-polling') - ); +ioApp.configure(function () { + ioApp.set("transports", ["websocket", "xhr-polling"]); + ioApp.set("polling duration", 10); + ioApp.set("log level", 2); // INFO - XHRPolling.prototype.doWrite = function(data) { + XHRPolling.prototype.doWrite = function (data) { HTTPPolling.prototype.doWrite.call(this); - var headers = { + const headers = { 'Content-Type': 'text/plain; charset=UTF-8', 'Content-Length': (data && Buffer.byteLength(data)) || 0 }; @@ -88,20 +75,33 @@ io.configure(function() { this.response.writeHead(200, headers); this.response.write(data); - // this.log.debug(this.name + ' writing', data); }; }); -io.sockets.on('connection', function(socket) { +ioApp.sockets.on('connection', function (socket) { numberOfClients++; - socket.on('disconnect', function() { + socket.on('disconnect', function () { numberOfClients--; }); }); +const subscriber = redisClient.duplicate(); +await subscriber.connect(); -if (env['redis_password']) { - redis.auth(env['redis_password']); -} -redis.subscribe(trackerConfig['redis_pubsub_channel']); +await subscriber.subscribe(trackerConfig['redis_pubsub_channel'], (message, channel) => { + const msgParsed = JSON.parse(message); + const logChannel = msgParsed['log_channel']; + if (!recentMessages[logChannel]) { + recentMessages[logChannel] = []; + } + const msgList = recentMessages[logChannel]; + msgList.push(msgParsed); + while (msgList.length > 20) { + msgList.shift(); + } + ioApp.of('/' + logChannel).emit('log_message', message); +}); +redisClient.on("error", (err) => { + console.error("redis error ", err); +});