Search code examples
node.jsudpupnpssdp

Error EADDRNOTAVAIL on socket.send() in node (SSDP protocol)


I'm trying to implement a UPnP discovery service tool (SSDP protocol), I did something similar in python following this post: https://www.electricmonk.nl/log/2016/07/05/exploring-upnp-with-python/ and I would like to port it to node (v. 8.6.0) and typescript however I'm getting the following error when I try to send the message (socket.send(...)):

{ Error: send EADDRNOTAVAIL 239.255.255.250:1900
    at Object._errnoException (util.js:1019:11)
    at _exceptionWithHostPort (util.js:1041:20)
    at SendWrap.afterSend [as oncomplete] (dgram.js:475:11)
  code: 'EADDRNOTAVAIL',
  errno: 'EADDRNOTAVAIL',
  syscall: 'send',
  address: '239.255.255.250',
  port: 1900 }

I've found a snippet of code for node, that makes this exact thing (https://coolaj86.com/articles/adventures-in-upnp-with-node-js/) and I think that my code is quite equivalent however I cannot see why my code isn't working

const dgram = require('dgram');
const socket = dgram.createSocket('udp4');

let msg_txt = 'M-SEARCH * HTTP/1.1\r\n' +
    'HOST:239.255.255.250:1900\r\n' +
    'ST:upnp:rootdevice\r\n' +
    'MX:2\r\n' +
    'MAN:"ssdp:discover"\r\n\r\n';

const message = Buffer.from(msg_txt);

socket.on('message', (msg: Buffer, info: any) => {
    console.log(msg.toString());
});

socket.bind({
    address: '239.255.255.250',
    port: 1900
}, (err) => {
    !!err && console.error(err);
});

socket.on('listening', () => {
    console.log('Sending msg...');
    socket.send(message, 0, message.length, 1900, '239.255.255.250', (err) => {
        !!err && console.error(err); // err != null
    });
});

I suspect that is a typical one-line-problem but after a while I couldn't find it out, any help is welcome.


Solution

  • I saw it, in node the API is a bit different, the binding should be against the '0.0.0.0' iface and the port 0 (for a random number), so changing the binding command to the following code just fix it:

    socket.bind({
        address: '0.0.0.0',
        port: 0
    }, (err) => {
        !!err && console.error(err);
    });
    

    In python I called to socket.recvfrom() method to get the UPnP devices responses, there is not an explicit socket binding.