1

Trying to "find" my RaspberryPi on the local WiFi by having it broadcast its IP via a datagram. New to this, but seems like it should work:

Broadcast message:

var Lighthouse = require('../lib/lighthouse.js');
var lh = new Lighthouse();
lh.startBroadcasting();

Listen for a message:

lh.listen();

Both NodeJS 6.7.0

Full code:

var Netmask = require('netmask').Netmask
var dgram = require('dgram');
var os = require('os');

var lighthouse = function Lighthouse() {
  this.timer = null;
  this.interval = 1;
  this.port = 3001;
  this.server = dgram.createSocket({type: "udp4", reuseAdr: true});
}

lighthouse.prototype.listen = function() {
  var self = this

  self.server.on('listening', () => {
    var address = self.server.address();
    console.log(`server listening ${address.address}:${address.port}`);
  });

  self.server.on('message', (msg, rinfo) => {
    console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
  });

  self.server.on('error', (err) => {
    console.log(`server error:\n${err.stack}`);
    server.close();
  });

  self.server.on('close', (err) => {
    console.log(`server close:\n${err.stack}`);
  });

  self.server.bind(self.port);
}

lighthouse.prototype.startBroadcasting = function() {
  var self = this;

  self.address = false;
  self.mask = false;

  var ifaces = os.networkInterfaces();
  Object.keys(ifaces).forEach(function (ifname) {
    ifaces[ifname].forEach(function (iface) {
      if ('IPv4' !== iface.family || iface.internal !== false) {
        return;
      }

      self.address = iface.address
      self.mask = iface.netmask
    });
  });

  if (self.address && self.mask) {
    if (self.timer) {
      clearInterval(self.timer);
    }

    self.message = new Buffer("{server: '" + self.address + "'}");

    block = new Netmask(self.address + '/' + self.mask);
    self.braodcast_address = block.broadcast;

    console.log(`Broadcasting to: ${self.braodcast_address}:${self.port}`);
    console.log(String(self.message));
  }

  self.server.bind(function() {
    self.server.setBroadcast(true);
    self.timer = setInterval(function() {
      self.rebroadcast();
    }, self.interval * 1000);
  });
}

lighthouse.prototype.rebroadcast = function() {
  var self = this;

  if (self.message) {
    self.server.send(self.message, 0, self.message.length, self.port, self.broadcast_address, function() {
      console.log(`Sent message: ${self.message}`);
    });
  }
}

module.exports = lighthouse;

This is the output when the client and server run on the same machine (either machine):

00:20 $ node debug/broadcast.js 
Broadcasting to: 10.0.1.255:3001
{server: '10.0.1.7'}
Sent message: {server: '10.0.1.7'}
Sent message: {server: '10.0.1.7'}
Sent message: {server: '10.0.1.7'}
Sent message: {server: '10.0.1.7'}

00:20 $ node debug/listen.js 
server listening 0.0.0.0:3001
server got: {server: '10.0.1.7'} from 127.0.0.1:50864
server got: {server: '10.0.1.7'} from 127.0.0.1:50864
server got: {server: '10.0.1.7'} from 127.0.0.1:50864
server got: {server: '10.0.1.7'} from 127.0.0.1:50864

Seems to make contact, however when on separate machines, the listening side stops with just server listening 0.0.0.0:3001

Is broadcast the wrong thing to do here? This answer seems to suggest it should be non-broadcast multicast. Maybe the AirPort router just blocks messages like this. tcpdump like sudo tcpdump -n udp port 3001 seems to show nothing.

Community
  • 1
  • 1
snakeoil
  • 497
  • 4
  • 12

1 Answers1

0

Found this similar answer. Made the following changes and it works great: https://gist.github.com/lacyrhoades/893ac68b156c63a721707f88bdcd7d35

Community
  • 1
  • 1
snakeoil
  • 497
  • 4
  • 12