configure method
Configure the link.
If argp is provided for argument parsing, it is used.
This includes:
- processing command-line arguments
- setting broker urls
- loading dsalink.json files
- loading or creating private keys
Implementation
bool configure({ArgParser? argp, OptionResultsHandler? optionsHandler}) {
_configured = true;
if (link != null) {
link?.close();
link = null;
}
argp ??= _argp ?? (_argp = ArgParser(allowTrailingOptions: !strictOptions));
argp.addOption(
'broker',
abbr: 'b',
help: 'Broker URL',
defaultsTo: 'http://127.0.0.1:8080/conn',
);
argp.addOption('name', abbr: 'n', help: 'Link Name');
argp.addOption('home', help: 'Home');
argp.addOption('token', help: 'Token');
argp.addOption('base-path', help: 'Base Path for dsalink');
argp.addOption('watch-file', help: 'Watch File for dsalink', hide: true);
argp.addOption('log-file', help: 'Log File for dsalink');
var logLevelNames = Level.LEVELS.map(_logLevelToName).toList();
logLevelNames.addAll(['auto', 'debug']);
argp.addOption(
'log',
abbr: 'l',
allowed: logLevelNames,
help: 'Log Level',
defaultsTo: 'AUTO',
);
argp.addFlag(
'help',
abbr: 'h',
help: 'Displays this Help Message',
negatable: false,
);
argp.addFlag(
'discover',
abbr: 'd',
help: 'Automatically Discover a Broker',
negatable: false,
);
argp.addFlag(
'strictTls',
help:
'Enforces valid SSL/TLS certificates for secure connections to '
'broker.',
);
var opts = _parsedArguments = argp.parse(args);
if (opts['log'] == 'auto') {
if (DEBUG_MODE) {
UpdateLogLevel('all');
} else {
UpdateLogLevel(defaultLogLevel);
}
} else {
UpdateLogLevel(opts['log']);
}
if (opts['base-path'] != null) {
_basePath = opts['base-path'];
if (_basePath.endsWith('/')) {
_basePath = _basePath.substring(0, _basePath.length - 1);
}
}
if (opts['watch-file'] != null) {
_watchFile = opts['watch-file'];
}
_logFile = opts['log-file'];
if (opts['strictTls']) {
strictTls = true;
}
if (_logFile != null) {
var file = File(_logFile!);
if (!file.existsSync()) {
file.createSync(recursive: true);
}
logger.clearListeners();
var out = _logFileOut = file.openWrite(mode: FileMode.append);
logger.onRecord.listen((record) {
out.writeln(
'[${DateTime.now()}][${record.level.name}] ${record.message}',
);
if (record.error != null) {
out.writeln(record.error);
}
if (record.stackTrace != null) {
out.writeln(record.stackTrace);
}
out.flush();
});
}
if (_watchFile != null) {
var file = File(_watchFile!);
StreamSubscription? sub;
sub = file.watch(events: FileSystemEvent.delete).listen((_) {
close();
sub?.cancel();
if (_logFileOut != null) {
try {
_logFileOut?.close();
} catch (e) {
logger.finest('Error closing log file.', e);
}
}
});
}
if (const bool.fromEnvironment(
'dsalink.debugger.console',
defaultValue: false,
)) {
readStdinLines().listen((String cmd) {
if (cmd == 'list-stored-nodes') {
if (provider is SimpleNodeProvider) {
var prov = provider as SimpleNodeProvider;
print(prov.nodes.keys.join('\n'));
} else {
print('Not a SimpleNodeProvider.');
}
} else if (cmd == 'list-stub-nodes') {
if (provider is SimpleNodeProvider) {
var prov = provider as SimpleNodeProvider;
for (var node in prov.nodes.values) {
var p = Path(node.path);
if (prov.nodes[p.parentPath] == null) {
print(node.path);
} else if (!prov.nodes[p.parentPath]!.children.containsKey(
p.name,
)) {
print(node.path);
}
}
} else {
print('Not a SimpleNodeProvider.');
}
}
});
}
{
dynamic runtimeConfig = Zone.current['dsalink.runtime.config'];
if (runtimeConfig != null) {
var closeHandler = () {
close();
if (_logFileOut != null) {
try {
_logFileOut?.close();
} catch (e) {
logger.finest('Error closing log file.', e);
}
}
};
runtimeConfig['closeHandler'] = closeHandler;
}
}
var helpStr =
'usage: $command [--broker URL] [--log LEVEL] [--name NAME] [--discover]';
if (opts['help']) {
print(helpStr);
print(argp.usage);
if (exitOnFailure) {
exit(1);
} else {
return false;
}
}
brokerUrl = opts['broker'];
if (brokerUrl == null && !opts['discover']) {
print(
'No Broker URL Specified. One of [--broker, --discover] is required.',
);
print(helpStr);
print(argp.usage);
if (exitOnFailure) {
exit(1);
} else {
return false;
}
}
String? name = opts['name'];
home = opts['home'];
token = opts['token'];
if (name != null) {
if (name.endsWith('-')) {
prefix = name;
} else {
prefix = '$name-';
}
}
// load configs
var dsalinkFile = File('$_basePath/dsalink.json');
if (dsalinkFile.existsSync()) {
dynamic e;
try {
var configStr = dsalinkFile.readAsStringSync();
dsalinkJson = DsaJson.decode(configStr);
} catch (err) {
e = err;
}
if (dsalinkJson == null) {
logger.severe('Invalid dsalink.json', e);
if (exitOnFailure) {
exit(1);
} else {
return false;
}
}
} else {
dsalinkJson = <String, dynamic>{};
}
if (brokerUrl != null) {
if (!brokerUrl!.startsWith('http')) {
brokerUrl = 'http://$brokerUrl';
}
}
var keyFile =
getConfig('key') == null
? File('$_basePath/.dsalink.key')
: File.fromUri(Uri.parse(getConfig('key') as String));
String? key;
try {
key = keyFile.readAsStringSync();
privateKey = PrivateKey.loadFromString(key);
} catch (err) {
logger.warning('Invalid Private Key', err);
}
if (key == null || key.length != 131) {
// 43 bytes d, 87 bytes Q, 1 space
// generate the key
if (DSRandom.instance.needsEntropy) {
late String macs;
if (Platform.isWindows) {
macs = Process.runSync('getmac', []).stdout.toString();
} else {
try {
macs = Process.runSync('arp', ['-an']).stdout.toString();
} catch (e) {
try {
var envs = '';
for (var i in Platform.environment.keys) {
envs += '$i=${Platform.environment[i]}\n';
}
macs = envs;
} catch (e) {
logger.finest('Cant get macs:', e);
}
}
}
// randomize the PRNG with the system mac (as well as timestamp)
DSRandom.instance.addEntropy(macs);
}
privateKey = PrivateKey.generateSync();
key = privateKey.saveToString();
if (savePrivateKey) {
keyFile.writeAsStringSync(key);
}
}
SimpleNode.initEncryption(privateKey.saveToString());
if (optionsHandler != null) {
optionsHandler(opts);
}
return true;
}