Skip to content

Instantly share code, notes, and snippets.

@FLYBYME
Created November 30, 2011 23:45
Show Gist options
  • Select an option

  • Save FLYBYME/1411970 to your computer and use it in GitHub Desktop.

Select an option

Save FLYBYME/1411970 to your computer and use it in GitHub Desktop.
/***
* Node modules
*/
var events = require('events');
var util = require('util');
var fs = require('fs');
/***
* Local modules
*/
var Exposed = require('./exposed');
var uid = require('./util').uid;
/***
* Global functions
*/
var globalFunctions = module.exports.globalFunctions = {}
/***
* Expose modules to every peer
* @param {String} Base name to the module
* @param {Object|Function} The module. Can be a function for the
* module to have onlt one method, or an Object for mulit methods.
*/
module.exports.exposeGlobal = function(mod, object) {
if( typeof (object) === 'object') {
var funcs = [];
for(var funcName in object) {
var funcObj = object[funcName];
if( typeof (funcObj) == 'function') {
globalFunctions[mod + '.' + funcName] = funcObj;
funcs.push(funcName);
} else if( typeof (funcObj) == 'object') {
module.exports.exposeGlobal(mod + '.' + funcName, funcObj);
}
}
console.log('exposing globalFunctions module: ' + mod + ' [funs: ' + funcs.join(', ') + ']')
} else if( typeof (object) == 'function') {
globalFunctions[mod] = object;
console.log('exposing globalFunctions ' + mod);
}
}
/**
* RPC-JSON style calls for partition.io
* Originally taken from rpc-socket
*
* @param {Object} initialized peer
*
* @return {Object}
*/
var RpcModule = module.exports.RpcModule = function(peer) {
var self = this;
events.EventEmitter.call(this);
this.peer = peer;
peer.rpc = this;
this.id = peer.id;
this.vows = {}
this.functions = Object.create(globalFunctions);
this.on('request', this.requestEvent);
this.on('handler', function(handler, exsosed, params) {
handler.apply(exsosed, params);
});
this.expose('list', function() {
var list = [];
for(var key in self.functions) {
this.set(key, 'function');
}
this.set('Array', Object.keys(self.functions));
this.send();
});
//peer.servent.emit('rpc', this)
}
/***
* Make it an event
*/
util.inherits(RpcModule, events.EventEmitter);
/***
* Write to the peer
*/
RpcModule.prototype.write = function(data) {
this.peer.send({
type : 'rpc',
data : data
});
};
/***
* Expose modules to every peer
* @param {String} Base name to the module
* @param {Object|Function} The module. Can be a function for the
* module to have onlt one method, or an Object for mulit methods.
*/
RpcModule.prototype.expose = function(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') {
this.functions[mod + '.' + funcName] = funcObj;
funcs.push(funcName);
} else if( typeof (funcObj) == 'object') {
this.expose(mod + '.' + funcName, funcObj);
}
}
console.log('exposing module: ' + mod + ' [funs: ' + funcs.join(', ') + '] ID: ' + this.id);
} else if( typeof (object) == 'function') {
this.functions[mod] = object;
console.log('exposing ' + mod);
}
return this;
};
/***
* Request event entry point for data
*/
RpcModule.prototype.requestEvent = function(data) {
if((data.hasOwnProperty('result') || data.hasOwnProperty('error') ) && data.hasOwnProperty('id') && this.vows.hasOwnProperty(data.id)) {
var vow = this.runVows(data);
//return;
return this.emit('handler', vow.handler, vow.exsosed, vow.params);
}
if(data.hasOwnProperty('error')) {
throw data.method;
}
if(!data.hasOwnProperty('id')) {
return this.write(this.runError(32600, null));
}
if(!(data.hasOwnProperty('method') && typeof (data.method) === 'string')) {
return this.write(this.runError(32600, data.id));
}
if(!data.hasOwnProperty('params') && Array.isArray(data.params)) {
return this.write(this.runError(32602, data.id));
}
if(!this.functions.hasOwnProperty(data.method)) {
return this.write(this.runError(32601, data.id));
}
var result = this.runExpose(data);
return this.emit('handler', result.handler, result.exsosed, result.params);
};
/***
* Ready for the exposed methods to be called
*/
RpcModule.prototype.runExpose = function(data) {
var exsosed = new Exposed(data, this.id, this);
var handler = this.functions[data.method];
console.log('RPC call with method: ' + data['method'] + ' ID: ' + this.id);
this.counter++;
return {
params : data.params,
handler : handler,
exsosed : exsosed
};
};
/***
* We have a request return so deal with it.
*/
RpcModule.prototype.runVows = function(data) {
var vow = this.vows[data.id];
//
return {
params : [data.error, data.result, data.id],
handler : vow.callBack,
exsosed : this
};
};
/***
* An error so just return it.
*/
RpcModule.prototype.runError = function(code, id) {
switch (code) {
case 32700:
return {
'result' : null,
'error' : {
'message' : 'Parse error',
'code' : code
},
'id' : id
};
case 32600:
return {
'result' : null,
'error' : {
'message' : 'Invalid Request',
'code' : code
},
'id' : id
};
case 32601:
return {
'result' : null,
'error' : {
'message' : 'Method not found.',
'code' : code
},
'id' : id
};
case 32602:
return {
'result' : null,
'error' : {
'message' : 'Invalid params.',
'code' : code
},
'id' : id
};
case 32603:
return {
'result' : null,
'error' : {
'message' : 'Internal error.',
'code' : code
},
'id' : id
};
default:
return {
'result' : null,
'error' : {
'message' : 'Server error.',
'code' : 32000
},
'id' : id
};
}
};
/***
* Invoke a method on the remote peer.
*/
RpcModule.prototype.invoke = function(method, params, callBack) {
var id = uid();
this.vows[id] = {
method : method,
params : params,
callBack : callBack
};
this.write({
id : id,
method : method,
peerId : this.id,
params : params
});
return this;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment