Question

I'm trying to write a Multicast DNS client in Node.js .

The goal is to show the same logical output of what I get running:

% dns-sd -G v4 irkitd2a8.local
DATE: ---Thu 20 Mar 2014---
20:38:21.426  ...STARTING...
Timestamp     A/R Flags if Hostname                               Address                                      TTL
20:38:22.571  Add     2  4 irkitd2a8.local.                       192.168.1.43                                 10

This is the UDP packets under the hood:

% sudo tcpdump -n udp port 5353
tcpdump: data link type PKTAP
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on pktap, link-type PKTAP (Packet Tap), capture size 65535 bytes
20:38:22.450804 IP 192.168.1.37.5353 > 224.0.0.251.5353: 0 A (QU)? irkitd2a8.local. (33)
20:38:22.571411 IP 192.168.1.43.5353 > 192.168.1.37.5353: 0*- [0q] 1/0/0 A 192.168.1.43 (43)

So I wrote this:

var PORT            = 5353;
var MULTICAST_GROUP = "224.0.0.251";

var dgram = require("dgram");

var client = dgram.createSocket("udp4");
var name = "IRKitD2A8";

var payload = new Buffer(
    [].concat( [ 0x00, 0x00, // ID
                 0x00, 0x00, // fixed
                 0x00, 0x01, // QDCount: number of entries in the Question Section
                 0x00, 0x00,
                 0x00, 0x00,
                 0x00, 0x00
               ],
               name.length,
               name.split("").map( function(letter) {
                   return letter.charCodeAt(0);
               }),
               "local".length,
               "local".split("").map( function(letter) {
                   return letter.charCodeAt(0);
               }),
               0x00, // NULL terminate
               [ 0x00, 0x01, // QTYPE
                 0x80, 0x01  // QCLASS
                 // http://tools.ietf.org/html/draft-cheshire-dnsext-multicastdns-06#section-6.5
                 // Multicast DNS defines the top bit in the class field of a DNS question as the "unicast response" bit.
               ]
             )
);
client.on("message", function(message, rinfo) {
    console.log("received: ",message,rinfo);
});
client.on("listening", function() {
    console.log("listening on ",client.address());

    client.setBroadcast(true);
    client.setTTL(64);
    client.setMulticastTTL(64);
    client.setMulticastLoopback(true);
    client.addMembership(MULTICAST_GROUP);
    client.send(payload, 0, payload.length, PORT, MULTICAST_GROUP, function(err,bytes) {
        console.log("err: "+err+" bytes: "+bytes);
        // client.close();
    });
});
client.on("close", function() {
    console.log("closed");
});
client.on("error", function(err) {
    console.log("error: ",err);
});
client.bind(5353);

When running this script, it outputs:

% node client.js
listening on  { address: '0.0.0.0', family: 'IPv4', port: 5353 }
err: null bytes: 33

And tcpdump outputs the same thing:

% sudo tcpdump -n udp port 5353
tcpdump: data link type PKTAP
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on pktap, link-type PKTAP (Packet Tap), capture size 65535 bytes
20:48:33.816076 IP 192.168.1.37.5353 > 224.0.0.251.5353: 0 A (QU)? IRKitD2A8.local. (33)
20:48:33.853892 IP 192.168.1.43.5353 > 192.168.1.37.5353: 0*- [0q] 1/0/0 A 192.168.1.43 (43)

So it looks like it's correctly sending the same packets as dns-sd does, and receiving the same thing, but the script's message event handler doesn't fire. Why? How to fix this and output the packets received?

I'm on MacOSX10.9, Node.js 0.10.25

Was it helpful?

Solution

Firewall.

I did:

  1. There were several entries named node in the processes list in System Preferences > Security & Privacy > Firewall, so I removed all node entries.
  2. Reboot MacOSX
  3. Restart script
  4. A dialog appeared to ask if I approve node listening for connections, I approved.
  5. Problem solved!

Sorry guys.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top