Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The current version may still have problems when multiple interfaces are present #43

Closed
webarchymeta opened this issue Jul 9, 2017 · 8 comments

Comments

@webarchymeta
Copy link

There are cases in which a host has multiple interfaces (e.g., the host is a host for virtual machines, etc.). However the bind and addMembership API has different semantics according the to manual:

  1. for bind:
    For UDP sockets, ... If address is not specified, the operating system will attempt to listen on all addresses. Once binding is complete, a 'listening' event is emitted and the optional callback function is called.
  2. for addMembership:
    ... If the multicastInterface argument is not specified, the operating system will choose one interface and will add membership to it. To add membership to every available interface, call addMembership multiple times, once per interface.

Therefore, due to this semantics mismatch, maybe the current listening handler:

    socket.on('listening', function () {
        if (!port) port = me.port = socket.address().port
        if (opts.multicast !== false) {
            try {
                socket.addMembership(ip, opts.interface);
            } catch (err) {
                that.emit('error', err)
            }
            socket.setMulticastTTL(opts.ttl || 255)
            socket.setMulticastLoopback(opts.loopback !== false)
        }
    })

Should be changed into something like:

    socket.on('listening', function () {
        if (!port) port = me.port = socket.address().port
        if (opts.multicast !== false) {
            try {
                if (opts.interfaces) {
                    opts.interfaces.forEach(mi => {
                        socket.addMembership(ip, mi);
                    });
                } else {
                    socket.addMembership(ip, opts.interface)
                }
            } catch (err) {
                that.emit('error', err)
            }
            socket.setMulticastTTL(opts.ttl || 255)
            socket.setMulticastLoopback(opts.loopback !== false)
        }
    })

where opts.interfaces can be used to specify a list of interfaces that the current instance wish to listen to and keep the opts.interface null (or undefined) when multiple interfaces are to be handled ?

(see also #41)

My suggestion haven't been tested in an active project, but it will be in a few days ...

@garci66
Copy link

garci66 commented Jul 24, 2017

There is an additional issue I just came accross when using multiple nics. You can't bind to 0.0.0.0:5353 and expect to receive the multicast traffic coming on the second nic. You need the call to bind to listen to 224.0.0.251.5353 instead. In my case (a quick and dirty test), I use the following:

var bind = thunky(function (cb) { if (!port) return cb(null) socket.once('error', cb) socket.bind(port, ip, function () { socket.removeListener('error', cb) cb(null) }) })

Otherwise, I was never receiving the packets in the process.
I belive regardless we should be binding to the group and not the 0.0.0.0 socket.

@garci66
Copy link

garci66 commented Jul 24, 2017

Looking at #38 it addresses this by keeping the bind call to just the port allways, regardless of number of interfaces specificied. I think this is nicer, especially since it will also catch unicast queries / replies.

@bnielsen1965
Copy link
Contributor

You need the call to bind to listen to 224.0.0.251.5353 instead

You may run into problems if you try this on a Windows operating system. I was using the method of binding to the multicast DNS IP address and it worked fine under linux but I ran into problems when using the code under Windows. I don't know if it is a Windows specific issue or if there was some conflict with some other application.

I should probably take pull request #42 from @panta and update the code for another PR, but for now I've reworked the code from @mafintosh into mdns-server (I know, shameless plug ;) and I've focused my efforts there for now.

@garci66
Copy link

garci66 commented Jul 24, 2017

Indeed regarding the multicast bind. It would also block you from receving unicast queries which the protocol supports. I've gone back to basically removing the interface's ip on the call to "bind" and be done with it. I will take a look at your code as well. Not sure what the difference is.

@webarchymeta
Copy link
Author

Yeah, binding to group ip and port, which is recommended in a StackOverflow discussion, only works on non-Windows systems (linux, macos) for me as well.

@webarchymeta
Copy link
Author

webarchymeta commented Jul 26, 2017

I have created my own fork that summarizes and incorporate all info here and on other branches. I am not sure if I should send a pull request since I also changed the coding style (to ES6), removed the thunky dependency, and the names and items in the options. The change is big on the surface, but the original spirit remains ...

@mafintosh
Copy link
Owner

Just pushed a new minor that should have much better support for this. Feedback welcome

@mafintosh
Copy link
Owner

If this is still not fixed, please re-open

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants