'use strict'
var __extend__ = function(child,parent){
child.prototype.__super__ = parent;
};
var imc = new function(){
var that = this;
that.Connection = function(link){
var that = this;
that.link_linkmap = {};
that.close_callback = [];
that.link = link;
that.send_msg = function(data){};
that.start_recv = function(recv_callback){};
that.close = function(){
var i;
for(i = 0;i < that.close_callback.length;i++){
that.close_callback[i](that);
}
};
};
that.Proxy = function(self_link,auth,conn_link){
var MSGTYPE_CALL = 'call';
var MSGTYPE_RET = 'ret';
var that = this;
var caller_retid_count = 0;
var conn_linkmap = {};
var conn_retidmap = {};
var callpath_root = {'child':{},'name':{},'filt':[]};
var walk_path = function(path,create){
var i;
var parts;
var part;
var cnode;
var nnode;
parts = path.split('/');
parts.pop();
cnode = callpath_root;
for(i = 0;i < parts.length;i++){
part = parts[i];
if(part in cnode.child){
cnode = cnode.child[part];
}else{
break;
}
}
if(create == true){
for(;i < parts.length;i++){
part = parts[i];
nnode = {'child':{},'name':{},'filt':[]};
cnode.child[part] = nnode;
cnode = nnode;
}
}else if(i < parts.length){
return undefined;
}
return cnode;
};
var route_call = function(caller_link,caller_retid,idendesc,dst,func_name,timeout,callback,param){
var i;
var j;
var part;
var dst_link;
var dst_path;
var caller_link;
var cnode;
var dpart;
var func;
var _add_wait_caller = function(conn_link){
conn_retidmap[conn_link][caller_retid] = {
'timeout':timeout,
'callback':callback
}
};
part = dst.split('/');
dst_link = part.slice(0,3).join('/') + '/'
dst_path = part.slice(3,-1);
if(dst_link == self_link){
cnode = callpath_root;
dpart = dst_path.slice(0);
for(i = 0;i < cnode.filt.length;i++){
cnode.filt[i](dpart,func_name);
}
for(i = 0;i < dst_path.length;i++){
if((cnode = cnode.child[dst_path[i]]) == undefined){
cnode = null;
break;
}
dpart.shift();
for(j = 0;j < cnode.filt.length;j++){
cnode.filt[j](dpart,func_name);
}
}
if(cnode != null && (func = cnode.name[func_name]) != undefined){
_add_wait_caller(self_link);
func.apply(undefined,[function(data){
if(self_link in conn_retidmap && caller_retid in conn_retidmap[self_link]){
delete conn_retidmap[self_link][caller_retid];
callback({'stat':true,'data':data});
}
}].concat(param));
}else{
callback({'stat':false,'data':'Enoexist'});
}
}else{
that.request_conn(dst_link,function(conn){
if(caller_link == self_link){
_add_wait_caller(conn.link);
}
send_msg_call(conn,caller_link,caller_retid,idendesc,dst,func_name,timeout,param);
});
}
};
var recv_dispatch = function(conn,data){
var msgo = JSON.parse(data);
if(msgo.type == MSGTYPE_CALL){
recv_msg_call(conn,msgo);
}else if(msgo.type == MSGTYPE_RET){
recv_msg_ret(conn,msgo);
}
};
var send_msg_call = function(conn,caller_link,caller_retid,idendesc,dst,func_name,timeout,param){
var msg = {
'type':MSGTYPE_CALL,
'caller_link':caller_link,
'caller_retid':caller_retid,
'idendesc':idendesc,
'dst':dst,
'func_name':func_name,
'timeout':timeout,
'param':param
};
conn.send_msg(JSON.stringify(msg));
};
var recv_msg_call = function(conn,msg){
var caller_link = msg.caller_link
var caller_retid = msg.caller_retid;
var timeout = msg.timeout;
var idendesc = msg.idendesc;
var dst = msg.dst;
var func_name = msg.func_name;
var param = msg.param;
route_call(caller_link,caller_retid,idendesc,dst,func_name,timeout,function(result){
that.request_conn(caller_retid,function(conn){
send_msg_ret(conn,caller_link,caller_retid,result);
});
},param);
};
var send_msg_ret = function(conn,caller_link,caller_retid,result){
var msg = {
'type':MSGTYPE_RET,
'caller_link':caller_link,
'caller_retid':caller_retid,
'result':result
};
conn.send_msg(JSON.stringify(msg));
};
var recv_msg_ret = function(conn,msg){
var caller_link = msg['caller_link'];
var caller_retid = msg['caller_retid'];
var result = msg['result'];
var wait;
if(caller_link == self_link){
if(conn.link in conn_retidmap && caller_retid in conn_retidmap[conn.link]){
wait = conn_retidmap[conn.link][caller_retid];
delete conn_retidmap[conn.link][caller_retid];
wait.callback(result);
}
}else{
request_conn(caller_link,function(conn){
send_msg_ret(conn,caller_link,caller_retid,result);
});
}
};
that.add_conn = function(conn){
conn_linkmap[conn.link] = conn;
conn_retidmap[conn.link] = {};
conn.start_recv(recv_dispatch);
};
that.link_conn = function(link,conn){
conn.link_linkmap[link] = true;
conn_linkmap[link] = conn;
};
that.unlink_conn = function(link){
conn = conn_linkmap[link];
delete conn_linkmap[link];
delete conn.link_linkmap[link];
};
that.del_conn = function(conn){
delete conn_linkmap[conn.link];
};
that.request_conn = function(link,callback){
var conn = conn_linkmap[link];
var _conn_cb = function(conn){
if(conn != null && conn.link != link){
that.link_conn(link,conn);
}
callback(conn);
};
if(conn != undefined){
_conn_cb(conn);
}else{
conn_link(link,_conn_cb);
}
};
that.call = function(dst,func_name,timeout,callback){
var i;
var params = new Array()
var caller_retid;
for(i = 4;i < arguments.length;i++){
params.push(arguments[i]);
}
caller_retid = self_link + '/' + caller_retid_count;
caller_retid_count += 1;
route_call(self_link,caller_retid,imc.Auth.get_current_idendesc(),dst,func_name,timeout,callback,params);
};
that.register_call = function(path,func_name,func){
var cnode;
cnode = walk_path(path,true);
cnode.name[func_name] = func;
};
that.unregister_call = function(path,func_name){
var cnode;
cnode = walk_path(path,true);
delete cnode.name[func_name];
}
that.register_filter = function(path,func){
var cnode;
cnode = walk_path(path,true);
cnode.filt.push(func);
};
that.unregister_filter = function(path,func){
var i;
var cnode;
var new_filt = new Array();
cnode = walk_path(path,true);
for(i = 0;i < cnode.filt.length;i++){
if(cnode.filt[i] != func){
new_filt.push(cnode.filt[i]);
}
}
cnode.filt.remove(func);
};
conn_retidmap[self_link] = {};
imc.Proxy.instance = that;
};
this.Auth = function(){
var that = this;
that.get_iden = function(idendesc){
return JSON.parse(JSON.parse(idendesc)[0]);
};
imc.Auth.change_current_iden = function(idendesc){
var iden = imc.Auth.instance.get_iden(idendesc);
imc.Auth.current_idendata = [iden,idendesc];
};
imc.Auth.get_current_iden = function(){
return imc.Auth.current_idendata[0];
};
imc.Auth.get_current_idendesc = function(){
return imc.Auth.current_idendata[1];
};
imc.Auth.current_idendata = null;
imc.Auth.instance = that;
};
};