Forum > Networking and Web Programming

Service discovery DNS-SD/mDNS (Bonjour, zeroconf)

(1/1)

Raskaton:
Hi!
Is any component for "Service discovery" DNS-SD/mDNS (also known as Bonjour, zeroconf) ?
RFC 6763 - DNS-SD
RFC 6763 - mDNS

This is Multicast UDP DNS-like protocol. I`m searching for two days, but no lack.

The mDNS multicast address is 224.0.0.251 for IPv4 and ff02::fb for IPv6 link-local addressing.
UDP Port 5353.

I tryed:

* Ararat Synapse 40.1
TDNSSend (uses dnssend from laz_synapse.lpk)
i did a trick, to enable Multicast and have responses. Works only for singleline response.
If answers from two or more devices/services than response is empty.  :(
No ipv6 support for host?
Maybe some differences in mDNS-response format of RR (Response Resource).
And very bad source: can't inherit and override methods - they are "private", not "protected"!  >:D
TMymDNS = class(TDNSSend) will be disaster.


* Indy10
IdDNSResolver (uses IdDNSResolver from indylaz.lpk)
no find a way to enable Multicast sending. No send - no response.
And big problems set Host to local - not cross-platform.
Can work with ipv6.
Clearer sources, but in v10 of Indy  IdDNSResolver inherited from TIdTCPConnection.
This all TCP stuff not needed in UDP mDNS  >:(
Rewriting this harder then Synapse.


* resolve
THostResolver (uses resolve from fcl-net)
No Multicast is posible. Realisation OS-specific.

Please, say that I dont need write it myself...
Sockets is so low-level and I am to old for that. Or Not enought old may be?  :D

bobby100:
https://forum.lazarus.freepascal.org/index.php/topic,57806.0.html - is this of any help?

Raskaton:

--- Quote from: bobby100 on April 15, 2023, 07:05:10 pm ---https://forum.lazarus.freepascal.org/index.php/topic,57806.0.html - is this of any help?

--- End quote ---
Thank you! I read this topic. It was helpful to know about IdIPMCastServer.
I read mDNS RFC. Unfortunately, this is a very complex problem.

I think implementing the protocol from scratch would be wrong. According to the RFC, mDNS is the direct successor of DNS. And it would be the right decision to take the working version of the DNS and inherit from it.

The protocols differ only in three small changes:

* A new field (logical flag) with a length of one bit "UNICAST-RESPONSE" has been added to the mDNS Query Question. QNAME, QTYPE, QCLASS unchanged.
* The boolean flag "CACHE-FLUSH" has also been added to the Response Resource Record. The remaining fields are RRNAME, RRTYPE, RDATA, etc. same.
* The RRTYPE=TXT record format has been changed. May contain JSON etc.
As I already wrote, it turned out to be a problem to inherit from existing DNS implementations.
It seems that the only way out is to copy the IdDNSResolver component, but change the parent to IdIPMCastServer, as in your solution. You will need to clean up a lot of dependencies inside :(
But there all structures are already declared. And they are tested! And parsing the response, compiling a request will require adding just a couple of flags. In theory :)

And the implementation of DNS-SD will have to be written from scratch.
In your example, obtaining IP is too simplified.

DNS-SD is a server running under the mDNS protocol, which must be run in a separate thread and continuously listen for changes. A device (service) can change its IP address, for example, by getting another one via DHCP. And then DNS-SD should immediately report that the service has a new address. Moreover, in the response of the SRV type, not only the HostName is reported, but also the Port! Moreover, the address may not match the address from which the answer was received!

In my case, the devices report the address and port of the REST Webservice to connect to.

Also, DNS-SD should listen on the special type "_services._dns-sd._udp" and respond to requests of this type automatically.
For example, in Linux, you can find all services with the Avahi utility:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---~ $ avahi-browse _services._dns-sd._udp+ wlp0s29u1u2 IPv4 _workstation                                  _tcp                 local+ wlp0s29u1u2 IPv4 _device-info                                  _tcp                 local+ wlp0s29u1u2 IPv4 _smb                                          _tcp                 local+ wlp0s29u1u2 IPv4 _ssh                                          _tcp                 local+ wlp0s29u1u2 IPv4 _ewelink                                      _tcp                 localAnd then, for each ServiceType="_ewelink._tcp", get all devices:

--- Code: Bash  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---~ $ avahi-browse _ewelink._tcp+ wlp0s29u1u2 IPv4 eWeLink_100c46f0                            _ewelink._tcp        local+ wlp0s29u1u2 IPv4 eWeLink_100c5910                            _ewelink._tcp        localThis was PTR query.
When DNS-SD know ServiceName "eWeLink_100c46f0._ewelink._tcp" it must form
SRV query and receive:
Hostname&Port like:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---0 0 1651 eWeLink_100c46f0.localand only then form A and AAAA querys for Hostname -> IP addr.

Not so simple.
I would like to find something already implemented and not read RFC DNS (6 big docs) :)
After all, in fact, my program just needs to know "192.168.0.13 : 1651".

P.S. eWeLink is iot-devices for SmartHome. Tuya have proprietry discovery UDP protocol under ports 6666 and 6667

bobby100:
Sounds complicated for my small brain  %)
I am sorry, but I can't help you any further.

Raskaton:
I've been experimenting with "Synapse 40.1" and using "TUDPBlockSocket" to implement mDNS from scratch, and encountered a bug on macOS when multiple applications use the same multicast port (OP_REUSEPORT). When I have time I will create a topic about this.

"TDNSSend" also turned out to be very difficult to adapt to mDNS. I did not manage to achieve stable work.

I'll have to try Indy.
Looks like my brain is small too :)

Navigation

[0] Message Index

Go to full version