UNPKG

dnode-spider

Version:

asynchronous rpc system for node.js, bi-direction and poly-direction communication...

113 lines (97 loc) 3.23 kB
var net = require('net'); var proto = require('dnode-protocol'); var EventEmitter = require('events').EventEmitter; var util = require('util'); var chunkParser = require('./chunkParser'); var uniqId = require('./uniqId'); var log = require('./log')(module); const EVENTS = { DATA: 'data', END: 'end', REQUEST: 'request', REMOTE: 'remote', CONNECTION: 'connection', }; const DEFAULT = { PORT: 5000, DELIMITER: "\0", }; var Client = function(client, server, api) { this.id = uniqId(); this.client = client; this.remote = null; this.buffer = ''; this.s = proto(api); this.client.on(EVENTS.DATA, this.onData.bind(this)); this.client.on(EVENTS.END, server.disconnection.bind(server, this)) this.s.on(EVENTS.REQUEST, this._write.bind(this)); this.s.on(EVENTS.REMOTE, this._onRemote.bind(this)); this.s.start(); } Client.prototype.onData = function(chunk) { chunkParser(this, chunk, function(data) { try { this.s.handle(JSON.parse(data)); } catch (e) { log.error(e.toString()); } }.bind(this)); } Client.prototype._onRemote = function(remote) { this.remote = remote; this.remote.$._setId(this.id); } Client.prototype._write = function(data) { this.client.write(JSON.stringify(data)+DEFAULT.DELIMITER); } var Server = function(api, options) { var self = this; var options = options || {}; var api = api || {}; var server = new net.Server(); api.$ = {}; api.$.proxy = this.proxy.bind(this); api.$.ids = this.ids.bind(this); api.$._changeId = this._changeId.bind(this); this.connections = {}; server.on(EVENTS.CONNECTION, this.onConnection.bind(this, api)); server.listen(options.port || DEFAULT.PORT, options.host); } util.inherits(Server, EventEmitter); Server.prototype.onConnection = function(api, client) { client = new Client(client, this, api); this.connections[client.id] = client; } Server.prototype.ids = function() { return Object.keys(this.connections); } Server.prototype.proxy = function(id, method) { if (!this.connections[id]) return log.warn('Connection with ['+id+'] does\'t exist'); if (!this.connections[id].remote) return log.warn('Connection with ['+id+'] does\'t have remote object'); if (!this.connections[id].remote[method]) return log.warn('Connection with ['+id+'] does\'t have remote method ['+method+']'); this.connections[id].remote[method].apply(this.connections[id].remote, Array.prototype.slice.call(arguments, 2)); } Server.prototype.broadcast = function(method) { var ids = this.ids(); for (var i = ids.length; i--;) if (this.connections[ids[i]] && this.connections[ids[i]].remote && this.connections[ids[i]].remote[method]) this.connections[ids[i]].remote[method].apply(this.connections[ids[i]].remote, Array.prototype.slice.call(arguments, 1)); } Server.prototype.disconnection = function(client) { this.emit('disconnection', this.connections[client.id]); this.connections[client.id] = null; delete this.connections[client.id]; } Server.prototype._changeId = function(id, newId, callback) { this.connections[newId] = this.connections[id]; this.connections[newId].id = newId; this.connections[id] = null; delete this.connections[id]; callback(); } module.exports = Server;