1 var net = require('net'); 2 var nowUtil = require('./nowUtil').nowUtil; 3 4 exports.initialize = function(nowjs){ 5 var fn = require('./function').init(nowjs); 6 7 function Support(host, port){ 8 this.socket = net.createConnection(port, host); 9 this._attachListeners(); 10 this.socket.setNoDelay(); 11 this.availableFunctions = {}; 12 } 13 14 Support.prototype._startHandshake = function(){ 15 this.socket.write(JSON.stringify({type:'new'})); 16 }; 17 18 Support.prototype._attachListeners = function(){ 19 var self = this; 20 this.socket.on('connect', function(){self._startHandshake();}); 21 this.socket.on('data', function(message){self._handleMessage(message);}); 22 }; 23 24 Support.prototype.getRemoteFunction = function(fn) { 25 var self = this; 26 if(this.availableFunctions[fn] == undefined){throw new Error("No such function: " + fn);}; 27 return function(){ 28 var args = []; 29 for (var i = 0, ii = arguments.length; i < ii; i++) { 30 args[i] = arguments[i]; 31 } 32 for (i = 0, ii = args.length; i < ii; i++) { 33 if (typeof args[i] === 'function') { 34 closureId = 'closure_' + args[i].name + '_' + nowUtil.generateRandomString(); 35 nowjs.closures[closureId] = args[i]; 36 args[i] = {fqn: closureId}; 37 setTimeout(function () { 38 nowjs.closures[closureId] = nowUtil.noop; 39 }, nowjs.options.closureTimeout); 40 } 41 } 42 43 self.socket.write(JSON.stringify({type: 'rfc',fqn:fn, args:args})); 44 }; 45 }; 46 47 Support.prototype._handleMessage = function(message){ 48 message = JSON.parse(message.toString()); 49 switch(message.type){ 50 case "usercall": 51 var user = nowjs.users[message.id]; 52 if (user && message.serverId !== nowjs.serverId) { 53 args = message.args; 54 // Convert any remote function stubs into remote functions 55 for (i = 0, ll = args.length; i < ll; i++) { 56 if (nowUtil.hasProperty(args[i], 'fqn')) { 57 obj = {host: message.host, port:message.port, fqn: args[i].fqn}; 58 args[i] = fn.closurecall.bind(obj); 59 } 60 } 61 theFunction = user.get(message.fqn); 62 theFunction.apply({}, args); 63 } 64 break; 65 case "multicall": 66 group = nowjs.getGroup(message.groupName); 67 //group = nowUtil.clone(group, {excludes: message.excludes}); 68 if (group) { 69 args = message.args; 70 // Convert any remote function stubs into remote functions 71 for (i = 0, ll = args.length; i < ll; i++) { 72 if (nowUtil.hasProperty(args[i], 'fqn')) { 73 obj = {socket: this.socket, host: message.host, port:message.port, fqn: args[i].fqn}; 74 args[i] = fn.closurecall.bind(obj); 75 } 76 } 77 group = nowUtil.clone(group, {fqn: message.fqn}); 78 nowjs.emit('multicall', group, args); 79 } 80 break; 81 case 'closurecall': 82 var args = message.args; 83 // Convert any remote function stubs into remote functions 84 for (i = 0, ll = args.length; i < ll; i++) { 85 if (nowUtil.hasProperty(args[i], 'fqn')) { 86 obj = {socket: this.socket, host: message.host, port:message.port, fqn: args[i].fqn}; 87 args[i] = fn.closurecall.bind(obj); 88 } 89 } 90 theFunction = nowjs.closures[message.fqn]; 91 theFunction.apply({}, args); 92 break; 93 case 'functionList': 94 var funcs = message.functions; 95 for(var i = 0, ll = funcs.length; i < ll; i++){ 96 this.availableFunctions[funcs[i]] = true; 97 } 98 } 99 }; 100 101 102 return Support; 103 }