'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.send_file = function(filekey,blob,callback){}; 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 MSGTYPE_SENDFILE = 'sendfile'; var MSGTYPE_ABORTFILE = 'abortfile'; var that = this; var caller_retid_count = 0; var conn_linkmap = {}; var conn_retidmap = {}; var callpath_root = {'child':{},'name':{},'filt':[]}; var info_filekeymap = {}; var conn_filekeymap = {}; function walk_path(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; } function route_call(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; function _add_wait_caller(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]; if(callback != null && callback != undefined){ callback({'stat':true,'data':data}); } } }].concat(param)); }else{ if(callback != null && callback != undefined){ 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); }); } } function ret_call(conn_link,caller_link,caller_retid,result){ var wait; 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]; }else{ return; } if(caller_link == self_link){ wait.callback(result); }else{ request_conn(caller_link,function(conn){ send_msg_ret(conn,caller_link,caller_retid,result); }); } } function route_sendfile(out_conn,src_link,filekey,filesize){ var info; function _send_cb(err){ if(del_wait_filekey(out_conn,filekey)){ return; } if(err != undefined){ out_conn.abort_file(filekey,err); send_msg_abortfile(out_conn,filekey,err); } ret_sendfile(filekey,err); } if(src_link != self_link){ //TODO return; } if((info = info_filekeymap[filekey]) == undefined){ return; } info.callback = _send_cb; add_wait_filekey(out_conn.link,filekey,info.blob.size,_send_cb); out_conn.send_file(filekey,info.blob,_send_cb); } function ret_sendfile(filekey,err){ var info; if((info = info_filekeymap[filekey]) == undefined){ return false; } delete info_filekeymap[filekey]; if(err == undefined){ info.result_callback('Success'); }else{ info.result_callback(err); } return true; } function add_wait_filekey(conn_link,filekey,filesize,callback){ conn_filekeymap[conn_link][filekey] = { 'callback':callback }; } function del_wait_filekey(conn_link,filekey){ if(conn_link in conn_filekeymap && filekey in conn_filekeymap[conn_link]){ delete conn_filekeymap[conn_link][filekey]; return true; }else{ return false; } } function recv_dispatch(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); }else if(msgo.type == MSGTYPE_SENDFILE){ recv_msg_sendfile(conn,msgo); }else if(msgo.type == MSGTYPE_ABORTFILE){ recv_msg_abortfile(conn,msgo); } } function send_msg_call(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)); } function recv_msg_call(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); } function send_msg_ret(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)); } function recv_msg_ret(conn,msg){ var caller_link = msg['caller_link']; var caller_retid = msg['caller_retid']; var result = msg['result']; ret_call(conn.link,caller_link,caller_retid,result); } function recv_msg_sendfile(conn,msg){ route_sendfile(conn,msg.src_link,msg.filekey,msg.filesize); } function send_msg_abortfile(conn,filekey,err){ var msg = { 'type':MSGTYPE_ABORTFILE, 'filekey':filekey, 'error':err }; conn.send_msg(JSON.stringify(msg)); } function recv_msg_abortfile(conn,msg){ var filekey = msg.filekey; var err = msg.error; if(conn.link in conn_filekeymap && filekey in conn_filekeymap[conn.link]){ conn_filekeymap[conn.link][filekey].callback(err); } } that.add_conn = function(conn){ conn_linkmap[conn.link] = conn; conn_retidmap[conn.link] = {}; conn_filekeymap[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){ retids = conn_retidmap[conn.link]; for(retid in retids){ ret_call(conn.link,caller_link,caller_retid,result); } filekeys = conn_filekeymap[conn.link]; for(filekey in filekeys){ filekeys[filekey].callback('Eclose'); } delete conn_retidmap[conn.link]; delete conn_linkmap[conn.link]; delete conn_filekeymap[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.sendfile = function(dst_link, blob, filekey_callback, result_callback, prog_callback){ var filekey = self_link + '_' + Math.random(); info_filekeymap[filekey] = { 'blob':blob, 'result_callback':result_callback, 'prog_callback':prog_callback, 'callback':function(err){ if(ret_sendfile(filekey,err) && err != undefined){ that.call(dst_link + 'imc/','abort_sendfile',65536,null,filekey,err); } } }; that.call(dst_link + 'imc/','pend_recvfile',65536,function(result){ filekey_callback(filekey); },self_link,filekey,blob.size); }; that.abortfile = function(filekey){ if((info = info_filekeymap[filekey]) != undefined){ info.callback('Eabort'); } }; 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); }; that.register_call('imc/','abort_sendfile', function(callback,filekey,err){ callback('Success'); ret_sendfile(filekey,'Eabort'); }); conn_retidmap[self_link] = {}; conn_filekeymap[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; }; };