forked from coolaj86/goldilocks.js
		
	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);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										144
									
								
								lib/mdns.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										144
									
								
								lib/mdns.js
									
									
									
									
									
										Normal file
									
								
							@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user