UNPKG

mar

Version:

MAR - Message & Reply, is a RPC library based on message exchange.

113 lines (89 loc) 2.36 kB
var net = require('net'); var Server = module.exports = function() { this._remoteMethods = {}; this._authRequired = false; var that = this; this._socket = net.createServer(function(s) { new ServerClient(that, s); }); this._socket.listen.apply(this._socket, arguments); }; Server.prototype.on = function(subject, fn) { if (subject == 'mar.auth') this._authRequired = true; this._remoteMethods[subject] = fn; }; Server.prototype._process = function(msg) { if (!this._remoteMethods[msg.subject]) { if (msg.reply) msg.reply('unsupported subject [' + msg.subject + ']'); return; } this._remoteMethods[msg.subject](msg); }; var ServerClient = function(server, socket) { this._server = server; this._socket = socket; this.authenticated = false; this._buffer = ''; var that = this; socket.setEncoding('utf8'); socket.setNoDelay(true); socket.on('data', function(data) { var tokens = that._tokenizer(data); for (var i = 0, len = tokens.length; i < len; i++) { that._process(tokens[i]); } }); }; ServerClient.prototype._process = function(msg) { try { msg = JSON.parse(msg); msg = this.prepare(msg); msg = this.auth(msg); if (msg) this._server._process(msg); } catch (e) { console.log('error', e); } }; ServerClient.prototype.auth = function(msg) { if (!this._server._authRequired) return msg; if (!this.authenticated && msg.subject != 'mar.auth') { msg.reply('auth required'); return; } var that = this; var original = msg.reply; msg.reply = function(err, data) { if (!err) that.authenticated = true; original(err, data); } return msg; }; ServerClient.prototype.prepare = function(msg) { var that = this; if (msg.reply) msg.reply = function(err, data) { var reply = { id: msg.id } if (err) { reply.err = err; that._socket.write(JSON.stringify(reply) + '\0'); return; } reply.data = data; that._socket.write(JSON.stringify(reply) + '\0'); } return msg; }; ServerClient.prototype._tokenizer = function(data) { this._buffer += data; var result = this._buffer.split('\0'); if (result.length == 1) return []; var last = result.pop(); if (last === '') { this._buffer = ''; return result; } else { this._buffer = last; return result; } };