547 lines
19 KiB
JavaScript
547 lines
19 KiB
JavaScript
/**
|
|
** ==============================
|
|
** 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 <path>] 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 <port>] UDP Server Port');
|
|
Io.out(' [-L <src port> <UDP dst [address:]port] UDP P2P Connection');
|
|
Io.out(' [-nokeepalive] Establish a new conncetion for each message.');
|
|
Io.out(' [-broker <ip[:ipport]>] Broker URL (Default: '+options.bip+': HTTP '+options.bport+' TCPNET '+(options.bport+100)+')');
|
|
Io.out(' [-dip <VLC UDP server IP>] (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(' <port> | <cap> | <capfile> | <path> | <parameter>=<value>..');
|
|
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<options.test;},schedules);
|
|
Sch.ScheduleBlock([function() {start=Perv.mtime();}]);
|
|
}
|
|
// Start up the network ..
|
|
network.init(network.start);
|
|
scheduler.Run();
|
|
|