dnode-spider
Version:
asynchronous rpc system for node.js, bi-direction and poly-direction communication...
206 lines (189 loc) • 6.01 kB
JavaScript
/* file deprecated, remove later */
var proto = require('dnode-protocol');
var net = require('net');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var uuid = require('node-uuid');
var encode = JSON.stringify;
var decode = JSON.parse;
const DEFAULT = {
PORT: 5000,
};
const RECONNECT_INTERVAL = 1000;
var buffs = [];
var chunks = [];
var _handle = function(data) {
var start = 0;
for (var j = 0; j < data.length; j++) {
if (data.readUInt8(j, true) === 0x00) {
var strdata = '';
if (chunks.length > 0)
strdata = chunks.join('');
strdata += data.slice(start, j).toString();
buffs.push(strdata);
chunks = [];
start = j + 1;
}
}
var chunk = null;
if (start < data.length)
chunk = data.slice(start, data.length);
for (var i = buffs.length; i--;) {
if (!buffs[i] || buffs[i].indexOf('namespace/') === 0)
continue;
try
{
this.handle(decode(buffs[i]));
} catch (e)
{
console.error(e);
}
}
buffs = [];
if (chunk)
chunks.push(chunk.toString());
}
var _getPid = function(client, server, data) {
var start = 0;
var buffs = [];
for (var j = 0; j < data.length; j++) {
if (data.readUInt8(j, true) === 0x00) {
buffs.push(data.slice(start, j).toString());
start = j + 1;
}
}
for (var i = buffs.length; i--;) {
buffs[i] = buffs[i].toString();
if (buffs[i].indexOf('namespace/') !== 0)
continue;
buffs[i] = buffs[i].replace('namespace/', '');
if (server.connections[buffs[i]]) {
if (!Array.isArray(server.connections[buffs[i]])) {
server.connections[buffs[i]] = [server.connections[buffs[i]]];
server.connections[buffs[i]].push(client);
console.warn('Duplicate connection with pid ['+buffs[i]+'], sum connection count is: ['+server.connections[buffs[i]].length+']');
}
else
server.connections[buffs[i]].push(client);
}
else {
server.connections[buffs[i]] = client;
}
client.uniqId = uuid.v1();
server.emit('connection', client.remote, client);
}
}
var _write = function(data) {
var data = encode(data);
this.write(createbuffer(data));
}
var createbuffer = function(data) {
var buf1 = new Buffer(data)
var buf2 = new Buffer(1);
buf2[0] = 0x00;
var resbuf = Buffer.concat([buf1, buf2]);
return resbuf;
}
var _serverEnd = function(client) {
for (var i in this.connections) {
if (Array.isArray(this.connections[i])) {
for (var j = this.connections[i].length; j--;)
if (this.connections[i][j].uniqId == client.uniqId)
this.connections[i].splice(j, 1);
if (this.connections[i].length == 0)
delete this.connections[i];
}
else if (this.connections[i].uniqId == client.uniqId) {
delete this.connections[i];
}
}
this.emit('disconnection', client);
}
var _proxy = function(pid, method) {
if (!this.connections[pid]) {
console.warn('connection pid ['+pid+'] does not exist');
return;
}
if (Array.isArray(this.connections[pid])) {
var connections = this.connections[pid];
for (var i = connections.length; i--;) {
if (connections[i].remote[method])
connections[i].remote[method].apply(connections[i].remote, Array.prototype.slice.call(arguments, 2));
else
console.warn('pid ['+pid+'] has no method '+method);
}
}
else {
if (this.connections[pid].remote[method])
this.connections[pid].remote[method].apply(this.connections[pid].remote, Array.prototype.slice.call(arguments, 2));
else
console.warn('pid ['+pid+'] has no method '+method);
}
}
var _ids = function(callback) {
callback(this.ids());
}
var Server = function(api, options) {
var self = this;
var options = options || {};
var api = api || {};
api.$ = {};
api.$.proxy = _proxy.bind(this);
api.$.ids = _ids.bind(this);
this.connections = {};
var server = new net.Server();
server.on('connection', function(client) {
var s = proto(api);
client.on('data', _handle.bind(s));
client.on('data', _getPid.bind(self, client, self));
client.on('end', _serverEnd.bind(self, client))
s.on('request', _write.bind(client));
s.on('remote', function(remote) { client.remote = remote; });
s.start();
});
server.listen(options.port || DEFAULT.PORT, options.host);
}
util.inherits(Server, EventEmitter);
Server.prototype.ids = function() {
return Object.keys(this.connections);
}
Server.prototype.broadcast = function(method) {
var ids = this.ids();
for (var i = ids.length; i--;) {
if (Array.isArray(this.connections[ids[i]])) {
var connections = this.connections[ids[i]];
for (var j = connections.length; j--;)
if (connections[j].remote[method])
connections[j].remote[method].apply(connections[j].remote, Array.prototype.slice.call(arguments, 1));
}
else if (this.connections[ids[i]].remote[method])
this.connections[ids[i]].remote[method].apply(this.connections[ids[i]].remote, Array.prototype.slice.call(arguments, 1));
}
}
var Client = function(api, options) {
var self = this;
var options = options || {};
var api = api || {};
var client = new net.Socket();
var c = proto(api);
this.remote = null;
this.nodeId = options.nodeId ? options.nodeId : process.pid;
c.on('request', _write.bind(client));
c.on('remote', function(remote) { self.remote = remote; self.emit('connection', remote); });
client.on('connect', client.write.bind(client, createbuffer('namespace/'+this.nodeId), c.start.bind(c)));
client.on('data', _handle.bind(c));
client.on('close', this._reconnect(client, options));
client.on('end', this._reconnect(client, options));
client.on('error', function(error) {});
client.connect(options.port || DEFAULT.PORT, options.host);
}
util.inherits(Client, EventEmitter);
Client.prototype._reconnect = function(client, options, event) {
return function() { setTimeout(client.connect.bind(client, options.port || DEFAULT.PORT, options.host), RECONNECT_INTERVAL); }
}
this.Server = this.Spider = Server;
this.Client = this.Fly = Client;
this.setSerializer = function(newencode, newdecode) {
encode = newencode;
decode = newdecode;
}