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.

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

mercurial