UNPKG

wotcs-api-system

Version:

Base system used to build WoTcs clans and players API

147 lines (136 loc) 5.96 kB
var cls = require('../base/class'); var WebSocketServer = require('ws').Server; var _ = require('underscore'); var WSClient = require('./ws_client'); var express = require('express'); module.exports = cls.Class.extend({ init: function(server, workerManager, router, config) { this.server = server; this.workerManager = workerManager; this.router = router; this.config = config; this.cookieParser = express.cookieParser(this.server.config.cookieSecret); this.wss = new WebSocketServer({server: this.server.server}); console.log('Websocket server created'); this.subscriptions = {}; this.clientCounter = 0; this.clients = {}; var self = this; this.wss.on('connection', function(ws) { self.cookieParser(ws.upgradeReq, null, function() { self.handleConnection(ws, ws.upgradeReq.signedCookies); }); }); }, handleConnection: function(ws, cookies){ var ID = this.clientCounter++; this.clients[ID] = new WSClient(ws, cookies.role); var self = this; ws.on('message', function(data) { var msg = JSON.parse(data); var action = msg.shift(); if(action == 'subscribe'){ ws.send(JSON.stringify([['sync', new Date()]])); _.each(msg, function(event) { self.addSubscriber(event, ID); }); }else if(action == 'execute'){ var worker = msg.shift(); var method = msg.shift(); if(self.clientCan(method, ID) && self.workerManager.workers[worker]){ msg.unshift(method); msg.push(function(){ var args = _.toArray(arguments); if(args[0] !== undefined){ args.unshift('execute.'+worker+'.'+method); var msg = JSON.stringify(args); self.clients[ID].send(msg); } }); self.workerManager.workers[worker].execute.apply(self.workerManager.workers[worker], msg); } }else if(action == 'execute-wm'){ var method = msg.shift(); if(self.clientCan('wm.'+method, ID) && self.workerManager[method]){ var ret = self.workerManager[method].apply(self.workerManager, msg); var args = ['execute-wm.'+method, ret]; var msg = JSON.stringify(args); self.clients[ID].send(msg); } }else if(action == 'execute-all'){ var method = msg.shift(); if(self.clientCan(method, ID)){ msg.unshift(method); var ret = {}; var send = _.after(_(self.workerManager.workers).size(),function(){ if(self.clients[ID]){ var msg = JSON.stringify(['execute-all.'+method, ret]); self.clients[ID].send(msg); } }); self.workerManager.forAll(function(worker, workerID){ var finalMsg = msg; finalMsg.push(function(){ ret[workerID] = {args: arguments, type: worker.type != 'cluster' ? worker.type : 'local'}; send(); }); worker.execute.apply(worker, msg); }); } }else if(action == 'server-worker'){ console.log('Server worker connected'); self.workerManager.addServerWorker(ws, msg.shift()); }else if(action == 'client-worker'){ console.log('Client worker connected'); ws.send(JSON.stringify(['sync', new Date()])); self.workerManager.addClientWorker(ws, msg.shift()); } }); ws.on('close', function() { delete self.clients[ID]; self.unsubscribe(ID); }); }, clientCan: function(method, ID) { var roles = this.config.execute.permissions[method] || []; roles = _.union(this.config.execute.permissions['*'], roles); var role = this.clients[ID].role; return _.include(roles, role); }, addSubscriber: function(event, ID) { var self = this; var eventer = this.workerManager; var prefix = ''; if(event.split('.')[0] == 'router'){ event = event.split('.').slice(1).join('.'); eventer = this.router; prefix = 'router.' } if(!this.subscriptions[prefix+event]){ var callbackID = eventer.on(event, function() { self.sendToSubscribers(prefix,event,arguments); }); this.subscriptions[prefix+event] = {ID: callbackID, clients: []}; } this.subscriptions[prefix+event].clients.push(ID); }, unsubscribe: function(ID) { _.each(this.subscriptions, function(subscription) { subscription.clients = _.reject(subscription.clients, function(cID) { return cID == ID; }); }); }, sendToSubscribers: function(prefix, event, args) { var self = this; args = _.toArray(args); if(args.pop() === true){ args.unshift(prefix+args.shift()); var msg = JSON.stringify(args); _.each(this.subscriptions[prefix+event].clients, function(ID) { var ws = self.clients[ID]; ws.send(msg); }); } } });