src/app.js

Wed, 13 Aug 2014 20:55:48 +0200

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 13 Aug 2014 20:55:48 +0200
changeset 1
9985a2a35a6a
child 3
42e83b3431d9
permissions
-rwxr-xr-x

Make general improvements to the package specification.

michael@0 1 #! /usr/bin/env nodejs
michael@0 2 //
michael@0 3 // mDNSGw - Zero Configuration DNS Gateway for Mesh Networks
michael@0 4 // Copyright © 2014 Michael Schloh von Bennewitz <michael@schloh.com>
michael@0 5 //
michael@0 6 // Permission to use, copy, modify, and/or distribute this software for
michael@0 7 // any purpose with or without fee is hereby granted, provided that the
michael@0 8 // above copyright notice and this permission notice appear in all copies.
michael@0 9 //
michael@0 10 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
michael@0 11 // WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
michael@0 12 // WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
michael@0 13 // AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
michael@0 14 // DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
michael@0 15 // PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
michael@0 16 // ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
michael@0 17 // THIS SOFTWARE.
michael@0 18 //
michael@0 19 // This file is part of mDNSGw, a Zero configuration DNS gateway
michael@0 20 // which can be found at http://dev.europalab.com/mdnsgw/
michael@0 21 //
michael@0 22 // app.js: ECMA JavaScript implementation
michael@0 23 //
michael@0 24
michael@0 25 /***********************************************************
michael@0 26 | ____ _ _ ____ ____ |
michael@0 27 | _ __ ___ | _ \| \ | / ___| / ___|_ __ |
michael@0 28 | | '_ ` _ \| | | | \| \___ \| | _\ \ /\ / / |
michael@0 29 | | | | | | | |_| | |\ |___) | |_| |\ V V / |
michael@0 30 | |_| |_| |_|____/|_| \_|____/ \____| \_/\_/ |
michael@0 31 | |
michael@0 32 | Requirements: Redis server with standard configuration |
michael@0 33 | NodeJS and NPM modules (see package.json) |
michael@0 34 | |
michael@0 35 | Execute: To start this application, launch it with the |
michael@0 36 | script named fork.js: $ ./fork.js |
michael@0 37 | |
michael@0 38 | Support: http://list.europalab.com/mailman/mdnsgs/ |
michael@0 39 | |
michael@0 40 ***********************************************************/
michael@0 41
michael@0 42 // import module dependencies
michael@0 43 var mdnsinst = require('mdns');
michael@0 44 var redisdat = require('redis');
michael@0 45 var nameinst = require('native-dns');
michael@0 46
michael@0 47
michael@0 48 // instantiate a new redis client
michael@0 49 // http://www.rediscookbook.org/
michael@0 50 var rediscli = redisdat.createClient();
michael@0 51 rediscli.on('error', function (error) {
michael@0 52 console.log('Error ' + error);
michael@0 53 });
michael@0 54
michael@0 55 // clear mDNS service keys
michael@0 56 rediscli.del('hostnames');
michael@0 57 // this is not working unfortunately for the loop
michael@0 58 rediscli.keys('*', function (error, replies) {
michael@0 59 replies.forEach(function (reply, ident) {
michael@0 60 rediscli.del(reply, function (error, value) {
michael@0 61 if (error) throw(error);
michael@0 62 });
michael@0 63 });
michael@0 64 });
michael@0 65
michael@0 66 // scan all advertised mDNS service types
michael@0 67 var browsall = mdnsinst.browseThemAll();
michael@0 68 browsall.on('serviceUp', function(service) {
michael@0 69 // iterate through hosts and watch accordingly
michael@0 70 if (service.type.name.match(/^[a-zA-Z0-9\-]+$/)) { // mdns module hack
michael@0 71 if (service.type.protocol == 'tcp') {
michael@0 72 var browserv = mdnsinst.createBrowser(mdnsinst.tcp(service.type.name));
michael@0 73 }
michael@0 74 else if (service.type.protocol == 'udp') {
michael@0 75 var browserv = mdnsinst.createBrowser(mdnsinst.udp(service.type.name));
michael@0 76 }
michael@0 77 else if (service.type.protocol == 'sctp') {
michael@0 78 var browserv = mdnsinst.createBrowser(mdnsinst.sctp(service.type.name));
michael@0 79 }
michael@0 80 else throw(error);
michael@0 81
michael@0 82 // common logic for all transports (TCP, UDP, SCTP, etcetera)
michael@0 83 browserv.on('serviceUp', function(service) {
michael@0 84 //console.log('service up: ', service);
michael@0 85 //{interfaceIndex: 2, type: {name: 'ssh', protocol: 'tcp', subtypes: [], fullyQualified: true}, replyDomain: 'local.', flags: 2, name: 'hostname-mich', networkInterface: 'eth0', fullname: 'hostname-mich._ssh._tcp.local.', host: 'hostname-mich.local.', port: 22, addresses: ['192.168.1.50']}
michael@0 86
michael@0 87 // insert one or more IP addresses for each hostname.local.
michael@0 88 rediscli.hset('hostnames', service.host.replace(/\.$/, ''), service.addresses);
michael@0 89 });
michael@0 90 browserv.on('serviceDown', function(service) {
michael@0 91 //console.log('service down: ', service);
michael@0 92 //FIXME: still need to selectively remove hosts
michael@0 93 });
michael@0 94 browserv.start();
michael@0 95 }
michael@0 96 });
michael@0 97 browsall.start();
michael@0 98
michael@0 99 // instantiate a new DNS server
michael@0 100 var nameserv = nameinst.createServer();
michael@0 101
michael@0 102 nameserv.on('request', function (request, response) {
michael@0 103 //console.log(request)
michael@0 104
michael@0 105 // ensure that requested hostname is present
michael@0 106 rediscli.hget('hostnames', request.question[0].name, function (error, value) {
michael@0 107 // handle unexpected errors
michael@0 108 if (error) throw(error);
michael@0 109
michael@0 110 if (value) { // the db succeeded in finding a match
michael@0 111 // populate the DNS response with the chosen hostname
michael@0 112 rediscli.hkeys('hostnames', function (error, replies) {
michael@0 113 replies.forEach(function (host, index) {
michael@0 114 if (request.question[0].name == host) {
michael@0 115 rediscli.hget('hostnames', host, function (error, value) {
michael@0 116 // handle unexpected errors
michael@0 117 if (error) throw(error);
michael@0 118
michael@0 119 // FIXME: still must handle multihomed hosts
michael@0 120 //// a host might have more than one address
michael@0 121 //value.forEach(function (addr, iter)
michael@0 122 // set the nameserver address
michael@0 123 response.answer.push(nameinst.A({
michael@0 124 name: host,
michael@0 125 address: value,
michael@0 126 ttl: 600,
michael@0 127 }));
michael@0 128 response.send();
michael@0 129 });
michael@0 130 }
michael@0 131 });
michael@0 132 });
michael@0 133 }
michael@0 134 else {
michael@0 135 response.answer.push(nameinst.A({
michael@0 136 name: request.question[0].name,
michael@0 137 address: '127.0.0.1',
michael@0 138 ttl: 600,
michael@0 139 }));
michael@0 140 response.send();
michael@0 141 }
michael@0 142 });
michael@0 143 });
michael@0 144
michael@0 145 // DNS error handler logic
michael@0 146 nameserv.on('error', function (err, buff, req, res) {
michael@0 147 console.log('DNS problem: ', err.stack);
michael@0 148 });
michael@0 149
michael@0 150 nameserv.serve(15353);
michael@0 151
michael@0 152 //// debug print all key and value database entries
michael@0 153 //rediscli.hgetall('hostnames', function (error, object) {console.dir(object);});
michael@0 154
michael@0 155 //// display stored mDNS service data entries
michael@0 156 //rediscli.hkeys('hostnames', function (error, replies) {
michael@0 157 // console.log(replies.length + ' replies:');
michael@0 158 // replies.forEach(function (reply, ident) {
michael@0 159 // console.log(' ' + ident + ': ' + reply);
michael@0 160 // });
michael@0 161 //});
michael@0 162
michael@0 163 //// block executes on program termination
michael@0 164 //rediscli.quit(); // cleanup db connection
michael@0 165 //browserv.stop(); // zombie scope too bad
michael@0 166 //browsall.stop();

mercurial