Open machinekoder opened 8 years ago
Tested https://github.com/mdns-js/node-mdns-js and it works. Good alternative until there is service discovery service.
node-mdns
does have service discovery. I've tried it between beaglebone (Debian) and laptop (NixOS) as well as host (ArchLinux) and virtualbox (Debian). The problem I had with node-mdns were:
libdnssd
). This is not a required dependency for avahi, so this libary needs to be installed manually./etc/nsswitch.conf
). This could be optional if the application explicitly resolves addresses through mdns (which could be the case for node-mdns-js), but it's less practical as you cannot let (for instance) zeromq do the resolving of its addresses.node-mdns
with regards to ipv4 and ipv6 that results in (amongst others) the error you describe. I noticed this when using it inside a Docker instance, but others have found it when using it on a Raspberry Pi. I've made a PR (https://github.com/agnat/node_mdns/pull/149), but that does a quick-fix, whereas an actual fix is required.That last one applies to your problem I think. The warnings are just there because node-mdns uses the Bonjour compatiblity library on Avahi (it does this because it already uses Bonjour for Mac OSX). It does discover machines, but it doesn't resolve their domain names correctly on some systems without the fix (https://github.com/agnat/node_mdns/pull/149). The fix was found by folks trying to make node-mdns work on Raspberry Pi. I ran into the problem when running inside Docker. I think it's triggered in these environments because they only support ipv4, whereas node-mdns tries to resolve addresses on both ipv4 and ipv6.
As for node-mdns-js
. I've tried it too: https://github.com/bobvanderlinden/node-machinetalk/tree/mdnsjs
However, what I did not like was:
node-mdns-js
couldn't find it. When you start Machinekit while the node app is running, it does find it. node-mdns
uses Avahi and Avahi caches all discovery states: it instantly knows all machines and services when we need them.
I'm not sure whether node-mdns-js
could do some kind of broadcast to ask for all machinekit services, but I was at the time not able to make this work.So, it's still a good option to investigate. Mainly I'd like to use node-mdns-js, because compilation on Windows is really annoying and it doesn't need any existing mdns daemon (no Bonjour on Windows).
Oh, this is also related to #11.
Is this the reason why I get "Machines:" box empty with BBM machinkeit running on same subnet?
node-mdns is in my opinion not worth fixing unless you want to completely rewrite it. Either we go with a discovery service or one has to build a node module based on jdns (https://github.com/psi-im/jdns) which is a proper cross-platform implementation.
Letting the OS resolve the hostname does not work on Windows since it does not support .local hostnames. So hostname lookup using mDNS needs to be done in the service itself.
@zhivko If you do not get errors like mentioned above, it's is a different issue. If you're on Linux, you can check what services Avahi has discovered using avahi-browse -a
.
@strahlex As for node_mdns, can you explain why it is not worth fixing?
Hmm, I was under the impression Bonjour was needed on Windows, which would do the resolving. I am not that familiar with the mdns protocol itself, but it seems we need discovery (passively listening for advertisements of mdns) and resolving/lookup (actively asking for addresses). Is that correct? If so, then I'd prefer using a pure JS solution or at least a solution that has the least amount of dependencies. That way Windows will have less problems compiling. node-mdns-js seems to do only the discovery part. multicast-dns seems to be able to resolve addresses. The combination would fit our purposes (I think/hope). Using jdns is possible, but I'm a bit worried it would make installation harder for some.
node-mdns is based on the Apple mDNSResolver library which is not a very good mDNS implementation, especially considering that node-machinetalk will mostly run on Linux hosts. Unless you fix the dependency on mDNSResolver you will not fix node-mdns.
One thing people always confuse is mDNS, Zeroconf and Bonjour.
mDNS is multicast DNS -> meaning DNS lookups based on multicast, how well multicast works strongly depends on your networking hardware, unfortunately a weak point that one should blame all these ISPs installing cheap routers in home network for.
mDNS is not purely passive, a good implementation queries the multicast group when started, newcomers to a multicast group announce themselves, queries are refreshed after a certain timeout (depending on networking hardware)
mDNS does not resolve any services it is just DNS over multicast, queries retourn pointers (A, AAA, SRV, PTR, ...)
DNS-SD is service discovery over DNS, meaning it works over multicast DNS and unicast DNS
Zeroconf is mDNS + DNS-SD -> node-mdns is actually a Zeroconf implementation
Bonjour is Apples name for Zeroconf
A DNS-SD service discovery consists of multiple DNS queries. I think 3 in total. Address resolution is part of it BUT it resolves the address of the host doing the announcement not the host announced. Therefore, one needs to do another mDNS query resolving the .local
hostnames. In Linux this is done by the system, however, it does not hurt to do it in the service discovery implementation.
DNS-SD also works over unicast. Avahi supports that type of lookup, this a very good fall back vehicle when you are in network with bad or no multicast support (e.g. RNDIS USB). Most implementations do not support that. This is huge advantage of JDNS or if you would create your own DNS-SD implementation (node-multicast-dns does only the multicast part, unicast lookup should be supported by node).
Ah! That explanation makes things click. Ok, so we need to avoid mDNSResolver (dns_sd.h).
I get your initial idea now. A service that supports all of it, but is still language independent. Bindings still need to be written though. I like the idea, but I don't like running a separate non-standard service in the background. How about using the dbus API for Avahi? It does basically the same, but it is a standard service that is available on many systems. There are good bindings for dbus for most languages already. Python already has the Avahi API implemented on top of dbus, the same could be done for Node.
So, these are the options and their pro/cons:
@bobvanderlinden the result of avahi-browse-a:
+ wlan0 IPv6 Log service on beaglebone.local pid 7298 _machinekit._tcp local
+ wlan0 IPv4 Log service on beaglebone.local pid 7298 _machinekit._tcp local
+ wlan0 IPv6 beaglebone Remote Disk Management local
+ wlan0 IPv6 klemenHp Remote Disk Management local
+ wlan0 IPv4 beaglebone Remote Disk Management local
+ wlan0 IPv4 klemenHp Remote Disk Management local
+ wlan0 IPv6 beaglebone [54:4a:16:c5:d0:2a] Workstation local
+ wlan0 IPv6 klemenHp [00:22:fa:c5:c4:50] Workstation local
+ wlan0 IPv4 beaglebone [54:4a:16:c5:d0:2a] Workstation local
+ wlan0 IPv4 klemenHp [00:22:fa:c5:c4:50] Workstation local
+ wlan0 IPv4 647310736 _teamviewer._tcp local
But machine box still empty. I guess It should show machinekit service on beaglebone?
When staring machinekit-example I get few errors like:
node index.js
*** WARNING *** The program 'nodejs' uses the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=nodejs>
*** WARNING *** The program 'nodejs' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi.
*** WARNING *** Please fix your application to use the native API of Avahi!
*** WARNING *** For more information see <http://0pointer.de/avahi-compat?s=libdns_sd&e=nodejs&f=DNSServiceRegister>
listening on http://localhost:3000/
Browser error { [Error: getaddrinfo -3008] code: -3008, errno: -3008, syscall: 'getaddrinfo' }
Browser error { [Error: getaddrinfo -3008] code: -3008, errno: -3008, syscall: 'getaddrinfo' }
@zhivko There is no Machinekit service shown at all. Have you started a Machinekit instance?
@bobvanderlinden If node will only run on Linux (which is likely, since it is the server) then the dbus avahi approach makes sense. There is actually an implementation for node based on dbus: https://github.com/izaakschroeder/node-avahi It is outdated an uses some weird 3rd party dbus interface, but I have also found dbus-native
a native javascript dbus implementation. Combining those two could give us reasonable results with low effort.
@strahlex machinekit is running on beaglebone. I have axis present and can jog steppers.
@bobvanderlinden Service discovery in Python uses exactly the same dbus interface. (https://github.com/strahlex/pymachinetalk/blob/master/pymachinetalk/dns_sd.py) However, the pythob-dbus implementation is not very good (uses gobject event loop). I am pretty sure node could handle this a lot better since it is made for multithreading.
@zhivko If you are running Axis you are not running Machinetalk. You need a (headless) Machinetalk capable configuration to try out node-machinetalk.
OK I think I have enabled remote in linuxcnc.ini, avahi shows now:
kz@klemenHp:/$ avahi-browse -a
+ wlan0 IPv6 HAL Rcommand service on beaglebone.local pid 8472 _machinekit._tcp local
+ wlan0 IPv6 HAL Rcomp service on beaglebone.local pid 8472 _machinekit._tcp local
+ wlan0 IPv6 HAL Group service on beaglebone.local pid 8472 _machinekit._tcp local
+ wlan0 IPv6 Log service on beaglebone.local pid 8447 _machinekit._tcp local
+ wlan0 IPv4 Previewstatus service on beaglebone.local pid 8864 _machinekit._tcp local
+ wlan0 IPv4 Preview service on beaglebone.local pid 8864 _machinekit._tcp local
+ wlan0 IPv4 Command service on beaglebone.local pid 8864 _machinekit._tcp local
+ wlan0 IPv4 Error service on beaglebone.local pid 8864 _machinekit._tcp local
+ wlan0 IPv4 Status service on beaglebone.local pid 8864 _machinekit._tcp local
+ wlan0 IPv4 File service on beaglebone.local pid 8864 _machinekit._tcp local
+ wlan0 IPv4 HAL Rcommand service on beaglebone.local pid 8472 _machinekit._tcp local
+ wlan0 IPv4 HAL Rcomp service on beaglebone.local pid 8472 _machinekit._tcp local
+ wlan0 IPv4 HAL Group service on beaglebone.local pid 8472 _machinekit._tcp local
+ wlan0 IPv4 Log service on beaglebone.local pid 8447 _machinekit._tcp local
+ wlan0 IPv6 beaglebone Remote Disk Management local
+ wlan0 IPv6 klemenHp Remote Disk Management local
+ wlan0 IPv4 beaglebone Remote Disk Management local
+ wlan0 IPv4 klemenHp Remote Disk Management local
+ wlan0 IPv6 beaglebone [54:4a:16:c5:d0:2a] Workstation local
+ wlan0 IPv6 klemenHp [00:22:fa:c5:c4:50] Workstation local
+ wlan0 IPv4 beaglebone [54:4a:16:c5:d0:2a] Workstation local
+ wlan0 IPv4 klemenHp [00:22:fa:c5:c4:50] Workstation local
But browsing to http://localhost:3000/ still show empty machines box.
Hmm, strange. Does the output of node tell you anything?
node-mdns uses the mDNSResponder interface which is pretty much broken on Linux. It looks like no proper mDNS implementation (at least not discovery-wise) for nodejs exists at the moment. I suggest making service discovery modular so that it can be used from nodejs and others (e.g. using avahi oder jdns). Idea: create a service discovery service (e.g. with the Python avahi bindings) and bind it to a well known ipc socket -> all machinetalk components can use it independent on the language