diff --git a/js/dos/appl/std.js b/js/dos/appl/std.js new file mode 100644 index 0000000..7176292 --- /dev/null +++ b/js/dos/appl/std.js @@ -0,0 +1,546 @@ +/** + ** ============================== + ** O O O OOOO + ** O O O O O O + ** O O O O O O + ** OOOO OOOO O OOO OOOO + ** O O O O O O O + ** O O O O O O O + ** OOOO OOOO O O OOOO + ** ============================== + ** Dr. Stefan Bosse http://www.bsslab.de + ** + ** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED + ** BY THE AUTHOR(S). + ** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED, + ** MODIFIED, OR OTHERWISE USED IN A CONTEXT + ** OUTSIDE OF THE SOFTWARE SYSTEM. + ** + ** $AUTHORS: Stefan Bosse + ** $INITIAL: (C) 2015-2017 bLAB + ** $CREATED: 21-5-15 + ** $VERSION: 1.5.3 + ** + ** $INFO: + ** + ** Standard Request Command Line Application + ** + ** $ENDOFINFO + */ +var log = 0; + +var Io = Require('com/io'); +//Io.trace_open('/tmp/std.trace'); + +if (typeof Shell == 'object') Io.set_stdout(Shell.stdout); + +var Net = Require('dos/network'); +var Sch = Require('dos/scheduler'); +var Conn = Require('dos/connection'); +var Std = Require('dos/std'); +var Dns = Require('dos/dns'); +var Cs = Require('dos/capset'); +var HostSrv = Require('dos/hostsrv'); +var util = Require('util'); +var Comp = Require('com/compat'); +var assert = Comp.assert; +var String = Comp.string; +var Array = Comp.array; +var Perv = Comp.pervasives; +var Args = Comp.args; +var Status = Net.Status; +var Command = Net.Command; + +var trace = Io.tracing; + +var options = { + bip:'localhost', + bport:3001, + broker: true, + caps:[], + cmd:Command.STD_INFO, + default:false, + delay:0, + dip : 'localhost', + dports : [], + echo:false, + env:{}, + fifo:false, + fifodir:'/tmp/broker', + fifochan:1, + hostname:Io.hostname(), + hostport:undefined, + http:false, + keepalive:true, + links:[], + monitor:0, + myip:'localhost', + overwrite:false, + params : [], + print : false, + servmode:false, + tcpnet:1, + test:0, + verbose:0 +}; + +var help=false; +var shift=''; + +var env={}; +options.env=env; +var argv = Io.getargs(); + +var out = function (s) {Io.out('[STD] '+s)}; + +function err(msg) { + out('Error: std '+Comp.array.tail(argv,2)+' => '+msg); + Io.exit(); +} + +function getip(str) { + var tokens = String.split(':',str); + if (tokens.length==2) return tokens[0]; + else if (tokens.length==1) return 'localhost'; + else return ''; + +} + +function getipport(str) { + var tokens = String.split(':', str); + if (tokens.length == 2) return Perv.int_of_string(tokens[1]); + else if (tokens.length == 1) return Perv.int_of_string(tokens[0]); + else return ''; + +} + +if (typeof Shell == 'object') Io.set_args(Shell.args); +Args.parse(argv, [ + [['-h','-help'],0,function() {help=true}], + [['-v','-verbose'],0,function() {options.verbose++;options.echo=true}], + [['-d','-default'],0,function() {options.default=true;}], + ['-overwrite',0,function() {options.overwrite=true;}], + ['-monitor',0,function() {options.monitor++;}], + ['-print',0,function() {options.print=true;}], + ['-server',0,function() {options.servmode=true;options.verbose++;}], + ['-test',1,function(val) {options.test=Perv.int_of_string(val);}], + ['-delay',1,function(val) {options.delay=Perv.int_of_string(val);}], + ['-broker',1,function(val){ + var tokens = Comp.string.split(':',val); + if (tokens.length==1) + options.bip=val; + else { + options.bip=tokens[0]; + options.bport=Perv.int_of_string(tokens[1]) + } + }], + ['-dip',1,function(val){options.dip=val}], + ['info',0,function() {options.cmd=Command.STD_INFO;}], + ['status',0,function() {options.cmd=Command.STD_STATUS;}], + ['age',0,function() {options.cmd=Command.STD_AGE;}], + ['setparams',0,function() {options.cmd=Command.STD_SETPARAMS;}], + ['touch',0,function() {options.cmd=Command.STD_TOUCH;}], + ['destroy',0,function() {options.cmd=Command.STD_DESTROY;}], + ['create',0,function() {options.cmd=Command.DNS_CREATE;}], + ['delete',0,function() {options.cmd=Command.DNS_DELETE;}], + ['-D',1,function(val){options.dports.push(Perv.int_of_string(val))}], + ['-L',2,function(val1,val2){options.links.push([Perv.int_of_string(val1),getip(val2),getipport(val2)])}], + ['-nokeepalive',0,function(val){options.keepalive=false;}], + ['-T',0,function(val){options.tcpnet=1;options.http=false;}], + ['-T2',0,function(val){options.tcpnet=2;options.http=false;}], + ['-H',0,function(val){options.http=true;options.tcpnet=0;}], + ['-F',1,function(val){ + options.fifo=true;options.tcpnet=0; + if (Comp.string.isNumeric(val)) options.fifochan=Perv.int_of_string(val); + else { + options.fifodir=val.split(/[0-9]./)[0]; + options.fifochan=(val.split(/[a-z]./).reverse()[0])||options.fifochan; + } + }], + [function(val){ + var pv = String.split('=',val); + if (Array.length(pv)==2) { + options.params.push(pv); + } else + options.caps.push(val); + }] +],2); + + +if ((help || options.cmd==undefined || options.caps.length==0) && !options.servmode) { + Io.out('usage: '+argv[0]+' '+argv[1]); + Io.out(' [-help -test #loops -delay #msec -print]'); + Io.out(' [-H -T -T2 -F ] Enable connection service'); + Io.out(' T: TCPIP, 1-ch H:HTTP T2: TCPIP, 2-ch'); + Io.out(' H: bport, T: bport+100'); + Io.out(' F: FIFO channel or full FS path with FIFO basename'); + Io.out(' (Default: -T)'); + Io.out(' [-D ] UDP Server Port'); + Io.out(' [-L ] Broker URL (Default: '+options.bip+': HTTP '+options.bport+' TCPNET '+(options.bport+100)+')'); + Io.out(' [-dip ] (Default: '+options.dip+')'); + Io.out(' [-v -verbose -monitor]'); + Io.out(' [-default -d] Ask broker server for default DNS root'); + Io.out(' [-overwrite AFS/DNS overwrite mode]'); + Io.out(' [-server] Host Server Mode (only)'); + Io.out(' info status age touch destroy setparams create delete'); + Io.out(' | | | | =..'); + return; +} + + +if (options.servmode) options.privhostport = Net.port_name('std'+options.hostname); +else options.privhostport = Net.uniqport(); +options.pubhostport = Net.prv2pub(options.privhostport); + +if (options.echo) out('['+Net.Print.port(options.pubhostport)+'] '+argv[1]+' '+ + Command.print(options.cmd)+ ' ' + options.caps); + +var scheduler = Sch.TaskScheduler(); +scheduler.Init(); +//scheduler.log(2); + + + +// Set-up the network environment .. +// typeof options : {http,tcpnet,dports,bip,bport,myip,verbose} +var network = Conn.setup(options); + +var StdInt = Std.StdInt(network.rpc); +var DnsInt = Dns.DnsInt(network.rpc); +var CsInt = Cs.CsInt(network.rpc); + +var cap; +if (env.rootdir) { + DnsInt.set_rootdir(env.rootdir); +} + + +var schedules=[]; + +var stat,data; + +function action (capp) { + var cap, + cs, + csnew, + capp, + row, + stat; + + function resolve (name,cb) { + var cap; + if (name !='/' && Io.exists(name)) { + /* + ** It is a capability file + */ + cap = Net.cap_of_file(name); + cb(Status.STD_OK,cap); + } else if (env.rootdir) { + /* + ** Look-up from DNS ... + */ + DnsInt.dns_lookup(env.rootdir,name,function (_stat,_cs) { + if (_stat==Status.STD_OK) cb(_stat,CsInt.cs_to_cap(_cs)); + else cb(_stat); + }) + } else { + /* + ** It is a capability string? + */ + var cp=Net.Parse.capability(name,0); + if (cp==undefined) { + /* + ** It is a port string? + */ + cp=Net.Parse.port(name,0); + if (cp!=undefined) { + cap=Net.Capability(cp.port); + } + } else { + cap=cp.cap; + } + if (cp==undefined) { + err('Invalid capability or port: '+name); + } + cb(Status.STD_OK,cap); + } + } + switch (options.cmd) { + case Command.STD_INFO: + Io.log(((log+options.verbose)<1)||('+std_info '+capp)); + schedules=Array.concat(schedules,[ + function () { + resolve(capp, function (_stat,_cap) { + stat=_stat; + cap=_cap; + }); + }, + function () { + if (stat!=Status.STD_OK) err('Cannot get info for '+capp+': '+Status.print(stat)); + if (!cap) err('Invalid capability ('+capp+')'); + Io.log(((log+options.verbose)<1)||('exec std_info '+Net.Print.capability(cap))); + StdInt.std_info(cap,function(_stat,_data) { + stat=_stat; + data=_data; + }); + }, + function () { + Io.log(((log+options.verbose)<1)||('finalize std_info '+ + Net.Print.capability(cap)+' ['+ + (data?data.length:0)+']')); + if (stat==Status.STD_OK) {if (options.delay > 0 || options.test==0 || options.print) out(data);} + else out(Status.print(stat)); + if ((options.delay > 0 || options.test==0) && options.monitor) out(network.router.status()); + if (options.delay > 0) Sch.Delay(options.delay); + } + ]); + break; + + case Command.STD_SETPARAMS: + Io.log(((log+options.verbose)<1)||('+std_setparams '+capp)); + schedules=Array.merge(schedules,[ + function () { + resolve(capp, function (_stat,_cap) { + stat=_stat; + cap=_cap; + }) + }, + function () { + if (stat!=Status.STD_OK) err('Cannot set params for '+capp+': '+Status.print(stat)); + if (!cap) err('Invalid capability ('+capp+')'); + Io.log(((log+options.verbose)<1)||('exec std_setparams '+Net.Print.capability(cap))); + StdInt.std_setparams(cap,params,function(_stat) { + stat=_stat; + }); + }, + function () { + Io.log(((log+options.verbose)<1)||('finalize std_setparams '+Net.Print.capability(cap))); + if (stat!=Status.STD_OK) out(Status.print(stat)); + if ((options.delay > 0 || options.test==0) && monitor) + out(network.router.status()); + if (options.delay > 0) Sch.Delay(options.delay); + } + ]); + break; + + case Command.STD_STATUS: + Io.log(((log+options.verbose)<1)||('+std_status '+Net.Print.capability(cap))); + schedules=Array.merge(schedules,[ + function () { + resolve(capp, function (_stat,_cap) { + stat=_stat; + cap=_cap; + }) + }, + function () { + if (stat!=Status.STD_OK) err('Cannot get status for '+capp+': '+Status.print(stat)); + if (!cap) err('Invalid capability ('+capp+')'); + StdInt.std_status(cap,function(_stat,_data) { + stat=_stat; + data=_data; + }); + }, + function () { + Io.log(((log+options.verbose)<1)||('finalize std_status '+ + Net.Print.capability(cap)+' ['+ + (data?data.length:0)+']')); + if (stat==Status.STD_OK) { + if (options.delay > 0 || options.test==0 || options.print) out(data); + } + else + Io.out(Status.print(stat)); + if ((options.delay > 0 || options.test==0) && options.monitor) + out(network.router.status()); + if (options.delay > 0) Sch.Delay(options.delay); + } + ]); + break; + + case Command.STD_AGE: + Io.log(((log+options.verbose)<1)||('+std_age '+Net.Print.capability(cap))); + schedules=Array.merge(schedules,[ + function () { + resolve(capp, function (_stat,_cap) { + stat=_stat; + cap=_cap; + }) + }, + function () { + if (stat!=Status.STD_OK) err('Cannot age '+capp+':'+Status.print(stat)); + if (!cap) err('Invalid capability ('+capp+')'); + StdInt.std_age(cap,function(_stat) { + stat=_stat; + }); + }, + function () { + if (options.delay > 0 || options.test==0) + out(Status.print(stat)); + if ((options.delay > 0 || options.test==0) && options.monitor) + out(network.router.status()); + if (options.delay > 0) Sch.Delay(options.delay); + } + ]); + break; + + case Command.DNS_CREATE: + Io.log(((log+options.verbose)<1)||('+dns_create '+capp)); + schedules=Array.merge(schedules,[ + function () { + var path=Comp.filename.dirname(capp); + console.log(path) + if (!env.rootdir) err('No DNS root specified for '+capp); + DnsInt.dns_lookup(env.rootdir,path,function (_stat,_cs) { + stat=_stat; + if (_stat==Status.STD_OK) cap = CsInt.cs_to_cap(_cs); + }) + }, + function () { + if (stat!=Status.STD_OK) err('Cannot create '+capp+': '+Status.print(stat)); + if (!cap) err('Invalid capability ('+capp+')'); + row=Comp.filename.basename(capp); + if (row=='') row='/'; + Io.log(((log+options.verbose)<1)||('exec dns_create I. lookup '+row+' in '+Net.Print.capability(cap))); + cs=CsInt.cs_singleton(cap); + DnsInt.dns_lookup(cs,row,function(_stat,_cs) { + stat=_stat; + }); + }, + function () { + Io.log(((log+options.verbose)<1)||('check dns_create '+ + Cs.Print.capset(cs))); + if (stat==Status.STD_OK && env.overwrite) { + DnsInt.dns_delete(cs,row,function(_stat) { + stat=_stat; + if (stat==Status.STD_OK) stat=Status.STD_NOTFOUND; + }); + } else if (stat!=Status.STD_NOTFOUND) + err('Cannot create '+capp+': '+ + (stat==Status.STD_OK?'exists already':Status.print(stat))); + }, + function () { + Io.log(((log+options.verbose)<1)||('create directory dns_create '+ + Cs.Print.capset(cs))); + if (stat==Status.STD_NOTFOUND) { + DnsInt.dns_create(cs,Dns.DNS_DEFAULT_COLS,function(_stat,_cs) { + stat=_stat; + csnew=_cs; + if (stat==Status.STD_OK) { + DnsInt.dns_append(cs,row,csnew,Dns.DNS_DEFAULT_RIGHTS,function(_stat,_cs) { + stat=_stat; + }); + } + }); + } + }, + function () { + Io.log(((log+options.verbose)<1)||('finalize dns_create '+ + Cs.Print.capset(csnew))); + out('create '+capp+': '+Status.print(stat)); + if (options.delay>0) Sch.Delay(options.delay); + }, + function () { + + } + ]); + break; + + case Command.DNS_DELETE: + Io.log(((log+options.verbose)<1)||('+dns_delete '+capp)); + schedules=Array.merge(schedules,[ + function () { + var path=Comp.filename.dirname(capp); + if (!env.rootdir) err('No DNS root specified for '+capp); + resolve(path, function (_stat,_cap) { + stat=_stat; + cap=_cap; + }); + }, + function () { + if (stat!=Status.STD_OK) err('Cannot delete '+capp+': '+Status.print(stat)); + if (!cap) err('Invalid capability ('+capp+')'); + row=Comp.filename.basename(capp); + if (row=='') row='/'; + Io.log(((log+options.verbose)<1)||('exec dns_delete I. lookup '+row+' in '+Net.Print.capability(cap))); + cs=CsInt.cs_singleton(cap); + DnsInt.dns_lookup(cs,row,function(_stat,_cs) { + stat=_stat; + }); + }, + function () { + Io.log(((log+options.verbose)<1)||('check dns_delete '+ + Cs.Print.capset(cs))); + if (stat==Status.STD_OK) { + DnsInt.dns_delete(cs,row,function(_stat) { + stat=_stat; + }); + } else + err('Cannot delete '+capp+': '+ + (stat==Status.STD_NOTFOUND?'exists not':Status.print(stat))); + }, + function () { + Io.log(((log+options.verbose)<1)||('finalize dns_delete '+ + CsInt.Print.capset(csnew))); + out('delete '+capp+': '+Status.print(stat)); + if (options.delay>0) Sch.Delay(options.delay); + }, + function () { + + } + ]); + break; + + default: + err('unsupported') + } +} +for (var i in options.caps) { + action (options.caps[i]); +} +var hostsrv; + +if (options.verbose) out('My host port: '+Net.Print.port(options.pubhostport)); +if (options.servmode) { + hostsrv = HostSrv.HostServer(scheduler, + network.rpc, + options, + 'STD.'+options.hostname, + options.env); +} else if (options.test==0) + Sch.ScheduleBlock(Array.merge(schedules, + [ + function () { + network.stop(); + Sch.Delay(10); + }, + function () { + process.exit(0) + } + ])); +else { + var start,stop; + Io.out('Test loops: '+options.test); + Sch.ScheduleBlock([ + function() { + stop = Perv.mtime(); + if (options.monitor) Io.out(network.router.status()); + if (options.delay==0) { + out('Test result: ' + ((options.test / (stop - start) * 1000) | 0) + ' ops/sec (' + + (((stop - start) * 1000 / options.test) | 0) + ' microsec/op)'); + } + }, + function () { + network.stop(); + Sch.Delay(10); + }, + function () { + process.exit(0); + }]); + Sch.ScheduleLoop(function(index) {return index