dnssd
Version:
Bonjour/Avahi-like service discovery in pure JavaScript
238 lines (180 loc) • 6.51 kB
JavaScript
;
var dnssd = require('../index.js');
//
//
main(process.argv);
//
//
function showHelp(reason) {
if (reason) console.log('\n' + reason);
console.log('\nUsage: dnssd-js <command>\n');
console.log('dnssd-js browse [type] [domain]');
console.log('dnssd-js advertise <type> <port> [name] [txt]');
console.log('dnssd-js query <record name> <record type>');
console.log('dnssd-js address <hostname> [v4/v6]');
process.exit();
}
function exit(err) {
if (err) console.log('\n' + err + '\n');
process.exit();
}
function padStart(value, len) {
var filler = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ' ';
var str = String(value);
var fill = String(filler);
var needed = len - str.length;
return needed > 0 ? fill.repeat(needed) + str : str;
}
function padEnd(value, len) {
var filler = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ' ';
var str = String(value);
var fill = String(filler);
var needed = len - str.length;
return needed > 0 ? str + fill.repeat(needed) : str;
}
function timestamp() {
var now = new Date();
var time = [padStart(now.getHours(), 2, 0), padStart(now.getMinutes(), 2, 0), padStart(now.getSeconds(), 2, 0), padStart(now.getMilliseconds(), 3, 0)];
return '[' + time.join(':') + ']';
}
function print(time, status, type, instance) {
console.log('%s %s %s %s', padEnd(time, 14), padEnd(status, 4), padEnd(type, 20), instance);
}
function browse(serviceType, domain) {
var browser = new dnssd.Browser(serviceType, { domain: domain });
// format to:
// [23:18:53:805] Up _http._tcp Test @ box.local. (169.254.22.58:4576)
browser.on('serviceUp', function (service) {
print(timestamp(), 'Up', '_' + service.type.name + '._' + service.type.protocol, service.name + ' @ ' + service.host + ' (' + service.addresses[0] + ':' + service.port + ')');
});
browser.on('serviceDown', function (service) {
print(timestamp(), 'Down', '_' + service.type.name + '._' + service.type.protocol, service.name + ' @ ' + service.host + ' (' + service.addresses[0] + ':' + service.port + ')');
});
browser.on('error', exit);
browser.start();
}
function browseAll(domain) {
console.log('Browsing for all available services:\n');
print('Time', 'U/D', 'Service Type', 'Instance');
print('----', '---', '------------', '--------');
var browser = new dnssd.Browser(dnssd.all(), { domain: domain });
var active = {};
browser.on('serviceUp', function (type) {
var serviceType = '_' + type.name + '._' + type.protocol;
// only start one browser for each new service type
if (!active[serviceType]) {
active[serviceType] = true;
browse(serviceType, domain);
}
});
browser.on('error', exit);
browser.start();
}
function browseType(type, domain) {
if (!type || type === 'all') return browseAll(domain);
var serviceType = void 0;
// wrap in case type validation fails
try {
serviceType = new dnssd.ServiceType(type);
} catch (err) {
exit('Bad service type: ' + err.message);
}
console.log('Browsing for "' + serviceType + '":\n');
print('Time', 'U/D', 'Service Type', 'Instance');
print('----', '---', '------------', '--------');
browse(serviceType, domain);
}
function advertise(type, portString, name, obj) {
var port = parseInt(portString, 10);
var txt = void 0,
advertisement = void 0;
if (!port) exit('Missing port number');
if (!Number.isInteger(port)) exit('Bad port number');
// parse txt string
if (obj) {
try {
txt = JSON.parse(obj);
} catch (err) {
exit('Problem parsing txt object: ' + txt.message);
}
}
// wrap in case advert args fail validation check
try {
advertisement = new dnssd.Advertisement(type, port, { name: name, txt: txt });
} catch (err) {
exit('Problem creating advertisement: ' + err.messsage);
}
console.log('Creating advertisement for "' + type + '"...');
advertisement.on('active', function () {
console.log('%s Advertisement now active', timestamp());
});
advertisement.on('instanceRenamed', function (instance) {
console.log('%s Advertisement instance renamed "%s" due to a conflict.', timestamp(), instance);
});
advertisement.on('hostRenamed', function (host) {
console.log('%s Advertisement hostname renamed "%s" due to a conflict.', timestamp(), host);
});
advertisement.on('stopped', function () {
console.log('%s Advertisement stopped.', timestamp());
exit();
});
advertisement.on('error', exit);
advertisement.start();
}
function query(name, type) {
if (!name) exit('Missing record name');
if (!type) exit('Missing record type');
// rrtype could be string (like TXT) or and int (like 16)
var rrtype = Number.isInteger(parseInt(type, 10)) ? parseInt(type, 10) : type;
var getRecord = void 0;
// wrap to check for validation errors
try {
getRecord = dnssd.resolve(name, rrtype);
} catch (err) {
exit(err);
}
getRecord.then(function (result) {
console.log('Found record: ' + result.answer);
}).catch(function (err) {
exit('Record not found. \nReason: ' + err.message);
});
}
function address(hostname) {
var IPv = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'v4/v6';
if (!hostname) exit('Missing hostname');
var getIPv4 = void 0,
getIPv6 = void 0;
// wrap to check for validation errors
try {
if (!!~IPv.indexOf('v4')) getIPv4 = dnssd.resolveA(hostname);
if (!!~IPv.indexOf('v6')) getIPv6 = dnssd.resolveAAAA(hostname);
} catch (err) {
exit(err);
}
if (!getIPv4 && !getIPv6) exit('Invalid address type given: ' + IPv);
Promise.all([getIPv4, getIPv6]).then(function (results) {
var IPv4 = results[0];
var IPv6 = results[1];
if (IPv4) console.log('Found IPv4 address: ' + IPv4);
if (IPv6) console.log('Found IPv6 address: ' + IPv6);
}).catch(function (err) {
exit('Address not found. \nReason: ' + err.message);
});
}
function main(args) {
var commands = {
browse: browseType,
register: advertise,
advertise: advertise,
query: query,
address: address
};
var command = args[2];
if (!command || command === '-h' || command === '--help') showHelp();
if (!(command in commands)) showHelp('Unknown command given');
commands[command].apply(null, args.slice(3));
process.on('SIGINT', exit);
process.on('SIGTERM', exit);
process.on('SIGQUIT', exit);
}