Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS Datagram - Receive IPv6 multicast

I'm trying to receive multicast datagrams over IPv6 in node.js. I had no problems doing it exactly same way over IPv4 (udp4), but trying to do the same for udp6 gives me EINVAL Errors on socket.addMembership call. Here is my code:

var dgram = require('dgram');
var server = dgram.createSocket('udp6');

var PORT = 12345;
var MULTICAST_ADDRESS = 'ff7e:230::1234';

server.on('message', function (message, remote) {
    console.log('Message from: ' + remote.address + ':' + remote.port +' - ' + message);
});

server.on('listening', function () {
  var address = server.address();
  console.log('UDP listening on ' + address.address + ":" + address.port);
  server.addMembership(MULTICAST_ADDRESS);
});

server.bind(PORT);

This causes:

    Error: addMembership EINVAL
            at new errnoException (dgram.js:454:11)
            at Socket.addMembership (dgram.js:396:11)
            at Socket.<anonymous> (/media/sf_projects/ipv6_multicast/server.js:57:10)
            at Socket.EventEmitter.emit (events.js:92:17)
            at startListening (dgram.js:141:10)
            at dgram.js:213:7
            at dns.js:72:18
            at process._tickCallback (node.js:415:13)
            at Function.Module.runMain (module.js:499:11)
            at startup (node.js:119:16)

When I comment out server.addMembership(MULTICAST_ADDRESS); the socket binds with success, but no datagrams are received.

I tried to call addMembership with my IPv6 as second argument, but this also gives EINVAL.

server.addMembership(MULTICAST_ADDRESS,  'fe80::a00:27ff:fed1:cac9');

I also tried to bind the socket to specific interface:

server.bind(PORT, 'fe80::a00:27ff:fed1:cac9');

a this also gives me EINVAL on bind method.

Here is output of my ifconfig:

    eth0      Link encap:Ethernet  HWaddr 08:00:27:d1:ca:c9  
                      inet addr:10.0.2.15  Bcast:10.0.2.255  Mask:255.255.255.0
                      inet6 addr: fe80::a00:27ff:fed1:cac9/64 Scope:Link
                      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
                      RX packets:8996 errors:0 dropped:0 overruns:0 frame:0
                      TX packets:6081 errors:0 dropped:0 overruns:0 carrier:0
                      collisions:0 txqueuelen:1000 
                      RX bytes:8389966 (8.3 MB)  TX bytes:510795 (510.7 KB)

    lo        Link encap:Local Loopback  
                      inet addr:127.0.0.1  Mask:255.0.0.0
                      inet6 addr: ::1/128 Scope:Host
                      UP LOOPBACK RUNNING  MTU:65536  Metric:1
                      RX packets:356 errors:0 dropped:0 overruns:0 frame:0
                      TX packets:356 errors:0 dropped:0 overruns:0 carrier:0
                      collisions:0 txqueuelen:0 
                      RX bytes:33534 (33.5 KB)  TX bytes:33534 (33.5 KB)
like image 880
Michael Prokopowicz Avatar asked Oct 01 '22 20:10

Michael Prokopowicz


1 Answers

If you want to bind to a link-local (fe80:) address you'll have to specify which link you want. Unfortunately I haven't found a way to do that for NodeJS. If you bind to a global IPv6 address it will work.

For the multicast support you seem to be out of luck... NodeJS only seems to support IPv4 multicast. A call to addMembership is implemented as a call to uv_udp_set_membership, which contains IPv4-only code. It parses the IP address with inet_addr, it calls setsockopt with the IP_ADD_MEMBERSHIP options while IPv6 needs IPV6_ADD_MEMBERSHIP etc.

NodeJS seems to be a bit behind on their IPv6 implementation :(

If you are interested you can see the source code here: https://github.com/joyent/node/blob/master/deps/uv/src/unix/udp.c

like image 188
Sander Steffann Avatar answered Oct 07 '22 19:10

Sander Steffann