Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

v0.0.6

  • Loading branch information...
commit 2714e4b5624ec92ca2b81dff26955bff607c69ad 1 parent f969f92
Tim authored
View
48 lib/dep.js
@@ -0,0 +1,48 @@
+/***
+ * Node modules
+ */
+var events = require('events');
+var util = require('util');
+var fs = require('fs');
+/***
+ * Local modules
+ */
+var uuid = require('./utils').uuid;
+
+var Dep = module.exports = function() {
+ this.contexts = {};
+};
+
+Dep.prototype.loadCode = function(block, locals, self, callBack) {
+
+ var argsKeys = [];
+ var argsObjs = [];
+
+ for(var i = 0; i < locals.length; i++) {
+ argsKeys.push(locals[i].key);
+ argsObjs.push(locals[i].val);
+ };
+
+ argsKeys.push('return (' + block + ').apply(this, [' + argsKeys.join(', ') + ']);');
+
+ var compiled = Function.apply({}, argsKeys);
+
+ var contexts = {
+ block : block,
+ compiled : compiled,
+ locals : locals,
+ self : self,
+ id : uuid(),
+ run : function() {
+ compiled.apply(self, argsObjs);
+ return contexts;
+ }
+ };
+ this.contexts[contexts.id] = contexts;
+ return contexts;
+
+};
+
+
+
+
View
152 lib/network.js
@@ -0,0 +1,152 @@
+var utils = require('./utils')
+
+var RpcModule = require('./rpc').RpcModule
+var Socket = require('./protocols/socket')
+
+var events = require('events');
+var util = require('util');
+var net = require('net');
+
+var crypto = require('crypto');
+/***
+ *
+ *
+ *
+ */
+
+var Network = module.exports = function() {
+
+ events.EventEmitter.call(this);
+ this.algorithm = '';
+ this.key = '';
+
+ this.sockets = {};
+
+};
+/***
+ * Make it an event
+ */
+util.inherits(Network, events.EventEmitter);
+
+Network.prototype.setAgorithm = function(algorithm) {
+ this.algorithm = algorithm;
+ return this;
+}
+/**
+ *
+ */
+
+Network.prototype.setKey = function(key) {
+ this.key = key;
+ return this;
+}
+/***
+ *
+ *
+ */
+Network.prototype.addTcpSocket = function(socket) {
+
+ var _socket = new Socket(socket);
+ var self = this;
+ var onReady = function() {
+
+ self.emit('rpc', _socket)
+
+ }
+ _socket.expose('ready', onReady);
+ /**
+ *
+ */
+ _socket.setAgorithm(this.algorithm);
+ _socket.setKey(this.key);
+
+ /**
+ *
+ */
+ return _socket;
+}
+/**
+ *
+ *
+ */
+Network.prototype.createTcpServer = function() {
+
+ var server = net.Server();
+ /**
+ * Listens for new connections and adds a peer for each one
+ */
+ function onConnection(socket) {
+ console.info('Peer connection request received');
+ /**
+ *
+ */
+ var _socket = this.addTcpSocket(socket);
+ /**
+ *
+ */
+ var onEnd = function() {
+ console.log('End event fired');
+ delete this.sockets[_socket.id];
+ this.emit('removed', _socket);
+ }
+ /**
+ *
+ */
+ this.sockets[_socket.id] = _socket.on('end', onEnd.bind(this));
+ _socket.invoke('ready', [], noop)
+ }
+
+ /**
+ * Print some info once we are listening
+ */
+ function onListen() {
+ console.info('Servent listening on: ' + JSON.stringify(server.address()));
+ }
+
+ /**
+ *
+ */
+ server.id = utils.uuid();
+
+ /**
+ *
+ */
+ server.on('connection', onConnection.bind(this));
+ server.on('listening', onListen.bind(this));
+ return server;
+}
+/**
+ *
+ *
+ *
+ */
+
+Network.prototype.connectAsTcp = function(port, host) {
+
+ var socket = net.connect(port, host);
+ /**
+ * When we connect, register the socket as a peer
+ */
+ function onConnect() {
+ var _socket = this.addTcpSocket(socket);
+ /**
+ *
+ */
+ var onEnd = function() {
+ console.log('End event fired');
+ delete this.sockets[_socket.id];
+ this.emit('removed', _socket);
+ }
+ /**
+ *
+ */
+ this.sockets[_socket.id] = _socket.on('end', onEnd.bind(this));
+
+ _socket.invoke('ready', [], noop)
+ }
+
+
+ socket.on('connect', onConnect.bind(this));
+};
+var noop = function() {
+};
View
24 lib/protocols/process.js
@@ -0,0 +1,24 @@
+var RpcModule = require('../rpc').RpcModule
+
+var Process = module.exports = function(p) {
+
+ var onWrite = function(data) {
+ p.send({
+ data : data
+ })
+ }
+ var onMessage = function(m) {
+ m.data ? this.requestEvent(m.data) : null;
+ }
+
+ p.on('message', onMessage.bind(this));
+
+ this.write = onWrite.bind(this);
+
+ RpcModule.call(this);
+
+};
+/**
+ * Inherits from EventEmitter
+ */
+require('util').inherits(Process, RpcModule);
View
24 lib/protocols/socket.io.js
@@ -0,0 +1,24 @@
+
+var RpcModule = require('../rpc').RpcModule
+
+var Io = module.exports = function(socket) {
+
+ RpcModule.call(this);
+ var onWrite = function(data) {
+ socket.emit('message', {
+ data : data
+ });
+ }
+ var onMessage = function(data) {
+ data.data ? this.requestEvent(data.data) : null;
+ }
+ socket.on('message', onMessage.bind(this));
+
+ this.write = onWrite.bind(this);
+
+
+};
+/**
+ * Inherits from EventEmitter
+ */
+require('util').inherits(Io, RpcModule);
View
93 lib/protocols/socket.js
@@ -0,0 +1,93 @@
+/**
+ *
+ */
+var events = require('events');
+var util = require('util');
+var net = require('net');
+var crypto = require('crypto');
+
+var utils = require('../utils')
+
+var RpcModule = require('../rpc').RpcModule
+
+var Socket = module.exports = function(socket) {
+
+ RpcModule.call(this);
+ /**
+ * Pass socket errors on up the chain.
+ * @private
+ */
+ var onError = function(error) {
+ throw error;
+ };
+ /**
+ * Handle our incoming data
+ * @private
+ */
+
+ var onData = function(data) {
+ data = data.toString();
+ if(data.indexOf('\n') > -1) {
+ var message = this.buffer.join('');
+ data = data.split('\n');
+ message += data.shift();
+ var decipher = crypto.createDecipher(this.algorithm, this.key);
+ var decrypted = decipher.update(message, 'hex', 'utf8') + decipher['final']('utf8');
+ this.buffer = [];
+
+ this.requestEvent(JSON.parse(decrypted));
+ data = data.join('\n');
+ if(data.length) {
+ onData.bind(this)(data);
+ }
+ } else {
+ this.buffer.push(data);
+ }
+ };
+ /**
+ * If end is received, then destroy the socket
+ */
+ var onEnd = function() {
+
+ }
+
+ this.destroyed = false;
+ this.socket = socket;
+
+ this.algorithm = '';
+ this.key = '';
+ this.buffer = [];
+
+ var onWrite = function(data) {
+ var cipher = crypto.createCipher(this.algorithm, this.key);
+ var encrypted = cipher.update(JSON.stringify(data), 'utf8', 'hex') + cipher['final']('hex') + '\n';
+ this.socket.writable ? this.socket.write(encrypted) : null;
+ };
+
+ this.write = onWrite.bind(this);
+
+ socket.on('data', onData.bind(this));
+ socket.on('error', onError.bind(this));
+ socket.on('end', onEnd.bind(this));
+
+};
+/**
+ * Inherits from EventEmitter
+ */
+util.inherits(Socket, RpcModule);
+
+Socket.prototype.setAgorithm = function(algorithm) {
+ this.algorithm = algorithm;
+}
+Socket.prototype.setKey = function(key) {
+ this.key = key;
+}
+/**
+ * Destroys the socket connection
+ */
+Socket.prototype.destroy = function() {
+ console.log('Received destroy request for peer: ' + this.id);
+ this.socket.destroy();
+ this.destroyed = true;
+ this.emit('end');
+};
View
209 lib/stack.js
@@ -0,0 +1,209 @@
+/***
+ * Node modules
+ */
+var events = require('events');
+var util = require('util');
+var fs = require('fs');
+/***
+ * Local modules
+ */
+var uuid = require('./utils').uuid;
+var Dep = require('./dep');
+var RpcModule = require('./rpc').RpcModule;
+
+var Exposed = function(data, stack, rpc) {
+ //
+ for(var key in stack) {
+ this[key] = stack[key];
+ }
+ this.id = data.id
+
+ this.method = data.method
+ this.params = data.params
+ //
+ this.callBack = function(data) {
+ rpc.write(data)
+ };
+ //
+ this.result = {}
+ this.err = {}
+ this.hasSent = false;
+}
+
+Exposed.prototype.send = Exposed.prototype.end = function() {
+ if(this.hasSent) {
+ throw new Error('should not sent twice.')
+ }
+ if(arguments.length >= 1) {
+ this.set(arguments[0], arguments[1])
+ }
+ this.callBack({
+ id : this.id,
+ result : this.result,
+ error : this.error['code'] ? this.error : null
+ })
+
+ this.hasSent = true;
+ return this;
+}
+Exposed.prototype.add = Exposed.prototype.set = function(key, val) {
+ this.result[key] = val;
+ return this;
+}
+
+Exposed.prototype.get = function(key) {
+ return this.result[key];
+};
+
+Exposed.prototype.error = function(msg, code) {
+ this.err = {
+ message : msg,
+ code : code || 1000,
+ method : this.method,
+ params : this.params
+ };
+ return this.send();
+};
+var Stack = module.exports = function() {
+ RpcModule.call(this);
+ var self = this;
+ var onWrite = function(data) {
+ self.emit('request', data)
+ }
+
+ this.write = onWrite.bind(this);
+ this.stack = {};
+
+ this.stackExpose({
+ create : function(rpc) {
+ console.log('create')
+ },
+ distroy : function(rpc) {
+ console.log('distroy')
+ },
+ locals : {
+
+ },
+ modules : {
+ load : function(block) {
+ var exposed = this;
+ console.log(block)
+ self.loadCode(block, [{
+ val : self,
+ key : 'rpc'
+ }], self, function() {
+ exposed.send()
+ })
+ }
+ },
+ name : 'stack'
+ })
+};
+/***
+ * Make it an event
+ */
+util.inherits(Stack, RpcModule);
+
+var expose = function(functions, mod, object) {
+ if( typeof (object) === 'object') {
+ var funcs = [];
+ var keys = Object.keys(object);
+ for(var i = keys.length - 1; i >= 0; i--) {
+
+ var funcObj = object[keys[i]];
+ var funcName = keys[i]
+ if( typeof (funcObj) == 'function') {
+
+ functions[mod + '.' + funcName] = funcObj;
+ funcs.push(funcName);
+ } else if( typeof (funcObj) == 'object') {
+ expose(functions, mod + '.' + funcName, funcObj);
+ }
+ }
+
+ console.log('exposing module: ' + mod + ' [funs: ' + funcs.join(', ') + '] ');
+ } else if( typeof (object) == 'function') {
+ functions[mod] = object;
+ console.log('exposing ' + mod);
+ }
+ return functions;
+};
+Stack.prototype.stackExpose = function(stack) {
+
+ if(this.validate(stack)) {
+
+ var readyStack = stack.locals
+
+ stack.create.apply(readyStack, [this]);
+
+ this.stack[stack.name] = readyStack;
+
+ expose(this.functions, stack.name, stack.modules)
+
+ }
+}
+/***
+ * Ready for the exposed methods to be called
+ */
+RpcModule.prototype.runExpose = function(data) {
+ var handler = this.functions[data.method];
+ var stack = this.stack[data.method.split('.')[0]];
+ var exsosed = new Exposed(data, stack || {}, this);
+ console.log('RPC call with method: ' + data['method']);
+ this.counter++;
+ return {
+ params : data.params,
+ handler : handler,
+ exsosed : exsosed
+ };
+};
+
+Stack.prototype.loadCode = function(block, locals, self, callBack) {
+
+ var argsKeys = [];
+ var argsObjs = [];
+
+ for(var i = 0; i < locals.length; i++) {
+ argsKeys.push(locals[i].key);
+ argsObjs.push(locals[i].val);
+ };
+
+ argsKeys.push('return (' + block + ').apply(this, [' + argsKeys.join(', ') + ']);');
+
+ var compiled = Function.apply(Function, argsKeys);
+
+ var contexts = {
+ block : block,
+ compiled : compiled,
+ locals : locals,
+ self : self,
+ id : uuid(),
+ run : function() {
+ compiled.apply(self, argsObjs);
+ return contexts;
+ }
+ };
+ callBack(contexts.run());
+}
+Stack.prototype.sendCode = function(block, callBack) {
+ this.invoke('stack.load', [block.toString()], callBack)
+}
+
+Stack.prototype.validate = function(stack) {
+ if(!stack.create && typeof stack.create !== 'function') {
+ throw new Error('stack.create missing or is not a function');
+ }
+ if(!stack.distroy && typeof stack.distroy !== 'function') {
+ throw new Error('stack.distroy missing or is not a function');
+ }
+ if(!stack.locals && typeof stack.locals !== 'object') {
+ throw new Error('stack.locals missing or is not a object');
+ }
+ if(!stack.modules && typeof stack.modules !== 'object') {
+ throw new Error('stack.modules missing or is not a object');
+ }
+ if(!stack.name && typeof stack.name !== 'string') {
+ throw new Error('stack.name missing or is not a string');
+ }
+ return true;
+};
View
35 test/cluster-tests.js
@@ -0,0 +1,35 @@
+var cluster = require('cluster');
+var http = require('http');
+var numCPUs = require('os').cpus().length;
+var p = require('../lib/protocols/process')
+
+var numReqs = 0;
+
+if(cluster.isMaster) {
+ // Fork workers.
+ for(var i = 0; i < numCPUs; i++) {
+
+ (new p(cluster.fork())).expose('numReqs', function(a) {
+
+ this.send('numReqs', numReqs++);
+ });
+ }
+
+ setInterval(function() {
+ console.log("numReqs =", numReqs);
+ }, 1000);
+} else {
+
+ var rpc = new p(process);
+ // Worker processes have a http server.
+ http.Server(function(req, res) {
+ res.writeHead(200);
+ // Send message to master process
+ rpc.invoke('numReqs', [], function(err, result) {
+ //console.log('Error: ', err)
+ //console.log('Result: ', result);
+
+ res.end("hello world!\nOh and numReqs: " + result.numReqs + "\n");
+ })
+ }).listen(8000);
+}
View
19 test/dep-test.js
@@ -0,0 +1,19 @@
+var Dep = require('../lib/dep')
+console.log(Dep)
+
+var dep = new Dep()
+
+console.log(dep)
+
+console.log(dep.loadCode( function(a) {
+
+ console.log('a ', a)
+ console.log('block')
+ console.log(this)
+
+}.toString(), [{
+ val : 'dsfsdf',
+ key : 'a'
+}], dep, function() {
+ console.log('callBack')
+}).run())
View
105 test/io-tests.js
@@ -0,0 +1,105 @@
+var i = require('socket.io');
+
+var Io = require('../lib/protocols/socket.io');
+
+var express = require('express');
+var app = require('express').createServer();
+var io = i.listen(app);
+console.log('io ', io)
+app.listen(8000);
+var generateData = function(n, floor) {
+ var data = [], p = (Math.random() * 11) + 1, i;
+ floor = (!floor && floor !== 0) ? 20 : floor;
+
+ for( i = 1; i < (n || 12); i++) {
+ data.push({
+ name : ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][i % 12],
+ 2008 : Math.floor(Math.max((Math.random() * 100), floor)),
+ 2009 : Math.floor(Math.max((Math.random() * 100), floor)),
+ 2010 : Math.floor(Math.max((Math.random() * 100), floor)),
+ data4 : Math.floor(Math.max((Math.random() * 100), floor)),
+ data5 : Math.floor(Math.max((Math.random() * 100), floor)),
+ data6 : Math.floor(Math.max((Math.random() * 100), floor)),
+ data7 : Math.floor(Math.max((Math.random() * 100), floor)),
+ data8 : Math.floor(Math.max((Math.random() * 100), floor)),
+ data9 : Math.floor(Math.max((Math.random() * 100), floor))
+ });
+ }
+ return data;
+}
+var numCount = 0;
+var histsData = [];
+var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+
+function pad(n) {
+ return n < 10 ? '0' + n.toString(10) : n.toString(10);
+}
+
+function timestamp() {
+ var d = new Date();
+ return [d.getDate(), months[d.getMonth()], [pad(d.getHours()), pad(d.getMinutes()), pad(d.getSeconds()), (d.getTime() + "").substr(-4, 4)].join(':')].join(' ');
+};
+
+setInterval(function() {
+
+ if(histsData.length >= 50) {
+ histsData.shift()
+ }
+ histsData.push({
+ name : timestamp(),
+ hits : numCount
+ })
+
+}, 5000)
+var sockets = {}
+
+io.sockets.on('connection', function(socket) {
+
+ var c = 0;
+ var n = 'No Nick!!'
+ var _socket = (new Io(socket)).expose('message', function(message) {
+
+ console.log(message)
+ this.send('count', ++c)
+
+ Object.keys(sockets).forEach(function(k) {
+ sockets[k].invoke('message', ['<strong>' + n + '</strong> : ' + message], function() {
+
+ })
+ })
+ }).expose('register', function(nick) {
+ n = nick
+ console.log(nick)
+ this.send('count', ++c)
+ Object.keys(sockets).forEach(function(k) {
+ sockets[k].invoke('message', ['<strong>SYSTEM</strong> : Welcome new user: <strong>' + nick + '</strong>'], function() {
+
+ })
+ })
+ });
+ socket.on('disconnect', function() {
+ delete sockets[_socket.is];
+ })
+ sockets[_socket.id] = _socket
+});
+
+app.configure(function() {
+ app.use(express.logger());
+ app.use(express.bodyParser());
+ app.use(express.methodOverride());
+ //app.use(express.static(__dirname + '/public'));
+ app.use(express.cookieParser());
+
+});
+app.use(express.static(__dirname));
+
+app.get('/', function(req, res) {
+ res.send()
+})
+
+app.get('/rpc.js', function(req, res) {
+ res.download('./rpc.js');
+})
+app.get('/client-io-test.js', function(req, res) {
+ res.download('./client-io-test.js');
+})
View
26 test/process-fork.js
@@ -0,0 +1,26 @@
+var cp = require('child_process');
+var p = require('../lib/protocols/process')
+var numCPUs = require('os').cpus().length;
+
+if(process.send) {
+
+ (new p(process)).invoke('test', [3454545], function(err, result) {
+ //console.log('Error: ', err)
+ //console.log('Result: ', result)
+
+ });
+} else {
+ var j = 0;
+ var callBack = function(err, result) {
+ console.log('Error: ', err)
+ console.log('Result: ', result);
+ if(++j === numCPUs) {
+ process.exit(0);
+ }
+ }
+ for(var i = 0; i < numCPUs; i++) {
+ (new p(cp.fork(__filename))).expose('test', function(a) {
+ this.send('a', a);
+ }).invoke('list', [], callBack);
+ }
+}
View
84 test/stack-test.js
@@ -0,0 +1,84 @@
+var cp = require('child_process');
+var Stack = require('../lib/stack');
+var stack = new Stack
+
+var s = {
+ create : function(rpc) {
+ console.log('create')
+ },
+ distroy : function(rpc) {
+ console.log('distroy')
+ },
+ locals : {
+ privateModule : function(cb) {
+ console.log('privateModule')
+ this.sub.func(cb)
+ },
+ sub : {
+ func : function(cb) {
+ console.log(this)
+ cb()
+ }
+ }
+ },
+ modules : {
+ publicModule : function() {
+ console.log(this)
+ console.log('publicModule')
+ var exposed = this;
+ this.privateModule(function() {
+ exposed.send()
+ })
+ }
+ },
+ name : 'ui'
+}
+stack.stackExpose(s)
+
+stack.invoke('list', [], function() {
+ console.log(arguments)
+ console.log(stack)
+ stack.invoke('ui.publicModule', [], function() {
+ console.log(arguments)
+ stack.sendCode(function(rpc) {
+ rpc.stackExpose({
+ create : function(rpc) {
+ console.log('create')
+ },
+ distroy : function(rpc) {
+ console.log('distroy')
+ },
+ locals : {
+ privateModule : function(cb) {
+ console.log('privateModule')
+ this.sub.func(cb)
+ },
+ sub : {
+ func : function(cb) {
+ console.log(this)
+ cb()
+ }
+ }
+ },
+ modules : {
+ publicModule : function() {
+ console.log(this)
+ console.log('publicModule')
+ var exposed = this;
+ this.privateModule(function() {
+ exposed.send()
+ })
+ }
+ },
+ name : 'remoteExposedStack'
+ }, function() {
+ console.log(arguments)
+ })
+ }, function() {
+ console.log(arguments)
+ stack.invoke('remoteExposedStack.publicModule', [], function() {
+ console.log(arguments)
+ })
+ })
+ })
+})
Please sign in to comment.
Something went wrong with that request. Please try again.