added simple mDNS responder
This commit is contained in:
parent
73d3396609
commit
1f8e44947f
|
@ -73,6 +73,9 @@ function readConfigAndRun(args) {
|
|||
if (!config.dns) {
|
||||
config.dns = { modules: { name: 'proxy', port: 3053 } };
|
||||
}
|
||||
if (!config.mdns) {
|
||||
config.mdns = { port: 5353, broadcast: '224.0.0.251', ttl: 300 };
|
||||
}
|
||||
if (!config.tcp) {
|
||||
config.tcp = {};
|
||||
}
|
||||
|
|
|
@ -225,5 +225,9 @@ module.exports.create = function (deps, config) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!config.mdns.disabled) {
|
||||
require('./mdns').start(deps, config);
|
||||
}
|
||||
|
||||
return PromiseA.all(listenPromises);
|
||||
};
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
'use strict';
|
||||
|
||||
var PromiseA = require('bluebird');
|
||||
var fs = PromiseA.promisifyAll(require('fs'));
|
||||
var idFilename = require('path').join(__dirname, '..', 'var', 'mdns-id');
|
||||
var queryName = '_cloud._tcp.local';
|
||||
|
||||
var randomId = {
|
||||
get: function () {
|
||||
return fs.readFileAsync(idFilename)
|
||||
.catch(function (err) {
|
||||
if (err.code !== 'ENOENT') {
|
||||
return PromiseA.reject(err);
|
||||
}
|
||||
var id = require('crypto').randomBytes(5).toString('hex');
|
||||
return randomId.set(id);
|
||||
});
|
||||
}
|
||||
|
||||
, set: function (value) {
|
||||
return fs.writeFileAsync(idFilename, value)
|
||||
.then(function () {
|
||||
return value;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function createResponse(name, packet, ttl) {
|
||||
var rpacket = {
|
||||
header: {
|
||||
id: packet.header.id
|
||||
, qr: 1
|
||||
, opcode: 0
|
||||
, aa: 1
|
||||
, tc: 0
|
||||
, rd: 0
|
||||
, ra: 0
|
||||
, res1: 0
|
||||
, res2: 0
|
||||
, res3: 0
|
||||
, rcode: 0
|
||||
, }
|
||||
, question: packet.question
|
||||
, answer: []
|
||||
, authority: []
|
||||
, additional: []
|
||||
, edns_options: []
|
||||
};
|
||||
|
||||
rpacket.answer.push({
|
||||
name: queryName
|
||||
, typeName: 'PTR'
|
||||
, ttl: ttl
|
||||
, className: 'IN'
|
||||
, data: name + '.' + queryName
|
||||
});
|
||||
|
||||
var ifaces = require('./local-ip').find();
|
||||
Object.keys(ifaces).forEach(function (iname) {
|
||||
var iface = ifaces[iname];
|
||||
|
||||
iface.ipv4.forEach(function (addr) {
|
||||
rpacket.additional.push({
|
||||
name: name + '.local'
|
||||
, typeName: 'A'
|
||||
, ttl: ttl
|
||||
, className: 'IN'
|
||||
, address: addr.address
|
||||
});
|
||||
});
|
||||
|
||||
iface.ipv6.forEach(function (addr) {
|
||||
rpacket.additional.push({
|
||||
name: name + '.local'
|
||||
, typeName: 'AAAA'
|
||||
, ttl: ttl
|
||||
, className: 'IN'
|
||||
, address: addr.address
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
rpacket.additional.push({
|
||||
name: name + '.' + queryName
|
||||
, typeName: 'SRV'
|
||||
, ttl: ttl
|
||||
, className: 'IN'
|
||||
, priority: 1
|
||||
, weight: 0
|
||||
, port: 443
|
||||
, target: name + ".local"
|
||||
});
|
||||
rpacket.additional.push({
|
||||
name: name + '._device-info._tcp.local'
|
||||
, typeName: 'TXT'
|
||||
, ttl: ttl
|
||||
, className: 'IN'
|
||||
, data: ["model=CloudHome1,1", "dappsvers=1"]
|
||||
});
|
||||
|
||||
return require('dns-suite').DNSPacket.write(rpacket);
|
||||
}
|
||||
|
||||
module.exports.start = function (deps, config) {
|
||||
var socket = require('dgram').createSocket({ type: 'udp4', reuseAddr: true });
|
||||
var dns = require('dns-suite');
|
||||
|
||||
socket.on('message', function (message, rinfo) {
|
||||
// console.log('Received %d bytes from %s:%d', message.length, rinfo.address, rinfo.port);
|
||||
|
||||
var packet;
|
||||
try {
|
||||
packet = dns.DNSPacket.parse(message);
|
||||
}
|
||||
catch (er) {
|
||||
// `dns-suite` actually errors on a lot of the packets floating around in our network,
|
||||
// so don't bother logging any errors. (We still use `dns-suite` because unlike `dns-js`
|
||||
// it can successfully craft the one packet we want to send.)
|
||||
return;
|
||||
}
|
||||
|
||||
// Only respond to queries.
|
||||
if (packet.header.qr !== 0) {
|
||||
return;
|
||||
}
|
||||
// Only respond if they were asking for cloud devices.
|
||||
if (packet.question.length !== 1 || packet.question[0].name !== queryName) {
|
||||
return;
|
||||
}
|
||||
|
||||
randomId.get().then(function (name) {
|
||||
var resp = createResponse(name, packet, config.mdns.ttl);
|
||||
socket.send(resp, config.mdns.port, config.mdns.broadcast);
|
||||
});
|
||||
});
|
||||
|
||||
socket.bind(config.mdns.port, function () {
|
||||
var addr = this.address();
|
||||
console.log('bound on UDP %s:%d for mDNS', addr.address, addr.port);
|
||||
|
||||
socket.setBroadcast(true);
|
||||
socket.addMembership(config.mdns.broadcast);
|
||||
});
|
||||
};
|
|
@ -41,6 +41,7 @@
|
|||
"bluebird": "^3.4.6",
|
||||
"body-parser": "git+https://github.com/expressjs/body-parser.git#1.16.1",
|
||||
"commander": "^2.9.0",
|
||||
"dns-suite": "git+https://git@git.daplie.com:Daplie/dns-suite#v1",
|
||||
"express": "git+https://github.com/expressjs/express.git#4.x",
|
||||
"finalhandler": "^0.4.0",
|
||||
"greenlock": "git+https://git.daplie.com/Daplie/node-greenlock.git#master",
|
||||
|
|
Loading…
Reference in New Issue