UNPKG

node-qwebchannel

Version:
190 lines (151 loc) 4.65 kB
var ws = require("nodejs-websocket") var isListening = false; var interfaces = {}; var MessageType = { SIGNAL: 1, INIT: 3, IDLE: 4, INVOKEMETHOD: 6, CONNECTTOSIGNAL: 7, RESPONSE: 10 }; // Serialize object and return it in JSON form function serializeObject(object) { var methods = []; var signals = []; for (var key in object) { if (typeof object[key] == "function") { methods.push(key); } else if (typeof object[key] == "object") { signals.push(key); } } return { methods: function() { return methods.map(function(key) { return [ key, methods.indexOf(key) + 1 ]; }); }(), signals: function() { return signals.map(function(key) { return [ key, signals.indexOf(key) + 1 ]; }); }(), properties: [] } } // Get all methods from the interface object function getInterfaceMethods(object) { var methods = []; for (var key in object) { if (typeof object[key] == "function") { methods.push(object[key]); } } return methods; } // Get all signals from the interface object function getInterfaceSignals(object) { var signals = []; for (var key in object) { if (typeof object[key] == "object") { signals.push(object[key]); } } return signals; } function interfaceExists(interfaceName) { if (typeof interfaces[interfaceName] == "undefined") { console.error("Interface " + interfaceName + " not found!"); return false; } return true; } // Handle INIT message type function handleInit(socket, message) { var data = {}; for (var interface in interfaces) { data = Object.assign(data, { [interface]: serializeObject(interfaces[interface]) }); } socket.sendText(JSON.stringify({ data: data, id: message.id, type: MessageType.RESPONSE })); } // Handle INVOKEMETHOD message type function handleInvokeMethod(message) { if (!interfaceExists(message.object)) return; var methods = getInterfaceMethods(interfaces[message.object]); if (message.method > methods.length) { console.error("Method index " + message.method + " not found in interface " + message.object + "!"); return; } if (methods[message.method - 1].length != message.args.length) { console.error("Invalid number of arguments"); return; } methods[message.method - 1].apply(interfaces[message.object], message.args); } // Handle CONNECTTOSIGNAL message type function handleConnectToSignal(socket, message) { if (!interfaceExists(message.object)) return; var signals = getInterfaceSignals(interfaces[message.object]); if (typeof signals[message.signal - 1] == "undefined") { console.error("Signal index " + message.signal + " not found in interface " + message.object + "!"); return; } signals[message.signal - 1].socket = socket; } module.exports = { listen: function(host, port) { ws.createServer(function(socket) { socket.on('text', function(text) { isListening = true; try { var message = JSON.parse(text); console.log(message); switch (message.type) { case MessageType.INIT: handleInit(socket, message); break; case MessageType.IDLE: break; case MessageType.INVOKEMETHOD: handleInvokeMethod(message); break; case MessageType.CONNECTTOSIGNAL: handleConnectToSignal(socket, message); } } catch (e) { console.error("Failed to parse message received from the client: " + e); } }); }).listen(port, host); }, registerInterface: function(interfaceName, interfaceObject) { function applyScopeToEmitFunctions() { var signalIndex = -1; for (var key in interfaceObject) { if (typeof interfaceObject[key] == "object") { interfaceObject[key].emit = interfaceObject[key].emit.bind({ interfaceName: interfaceName, signalName: key, signalIndex: ++signalIndex + 1 }); } } } if (isListening) { console.error("Cannot register interface " + interfaceName + " while listening"); return false; } if (typeof interfaces[interfaceName] != "undefined") { console.error("The interface " + interfaceName + " is already registered!"); return false; } interfaces[interfaceName] = interfaceObject; applyScopeToEmitFunctions(); return interfaceObject; }, method: function(callback) { return callback; }, signal: { emit: function() { var message = { object: this.interfaceName, signal: this.signalIndex, args: Array.prototype.slice.call(arguments), type: MessageType.SIGNAL }; interfaces[this.interfaceName][this.signalName].socket.sendText(JSON.stringify(message)); } } }