zum hintergrund: neben upnp/ssdp gibt es mit mdns/dns-sd einen zweiten weit verbreiteten ansatz um dienste in einem lokalen netz bekannt zu geben und zu suchen bzw. zu finden.
da es sich mit meinem discovery modul aus diesem thread:
https://forum.fhem.de/index.php/topic,67368.msg880001.html#msg880001 noch etwas hin zieht, inzwischen aber auch ein upnp/ssdp modul entsteht und ich weitere doppel entwicklungen vermeiden möchte habe ich einen schon sinnvoll benutzbaren mdns teil des discovery moduls aufgeräumt und standallone benutzbar gemacht.
was machen die routinen: man kann damit im one-shot unicast modus browsen und resolven. allerdings mit der auswertung mehrerer resource records (primary und additional) in einer antwort sowie dem empfangen von mehreren antworten auf eine anfrage innerhalb des gesetzten timeouts. unterstützt werden aktuell a, aaaa, ptr, txt und srv records in der antwort sowie alle typen in der anfrage.
das ganze funktioniert komplett ohne externe abhängigkeiten (außer fhem

) und ist non-blocking. es sollte möglich sein beliebig viele parallele anfragen abzusetzen.
der code ist sehr ähnlich zu den bereits in fhem vorhandenen non-blocking dns routinen. der hauptunterschied besteht darin das er genereller, d.h. für mehr resource records und mehrere antworten, implementiert ist und das natürlich mdns verwendet wird statt eines konfigurierten lokalen nameservers. ausserdem ist das interface eher an HttpUtils_NonblockingGet als an HttpUtils_gethostbyname orientiert.
noch nicht enthalten ist: das permanente lauschen und sammeln im hintergrund auf mdns multicast nachrichten an port 5353. das läuft zwar auch schon, aktuell brauche ich dafür aber das perl IO::Socket::Multicast modul und ich würde gerne ohne auskommen. ebenfalls ist aktuell ein cache für die antworten deaktiviert da er nur mit einem einzelnen resource record pro anfrage klar kommt und vermutlich der hintergrund dienst sowieso sinnvoller als ein reiner cache ist.
mögliche beispielaufrufe sehen etwa so aus:
{ mDNS::mDNS_Lookup({qname=>'_services._dns-sd._udp', callback=>\&mDNS::mDNS_dumpResult}) }
findet
alle im lokalen netz angebotenen
service typen{ mDNS::mDNS_Lookup({qname=>'_http._tcp', callback=>\&mDNS::mDNS_dumpResult}) }
infos zu
allen im lokalen netz angebotenen
http dienste{ mDNS::mDNS_Lookup({qname=>'_hue._tcp', callback=>\&mDNS::mDNS_dumpResult}) }
infos zu
allen im lokalen netz vorhandenen
hue bridges{ mDNS::mDNS_Lookup({qname=>'_coap._tcp', callback=>\&mDNS::mDNS_dumpResult}) }
infos zu
allen im lokalen netz vorhandenen
coap diensten. das sind z.b.
tradfri gateways und vermutlich auch
shellys
{ mDNS::mDNS_Lookup({qname=>'_ipp._tcp',singleshot=>1, callback=>\&mDNS::mDNS_dumpResult}) }
infos zum
ersten im lokalen netz gefundenen ipp drucker
{ mDNS::mDNS_Lookup({qname=>'<hostname>', qtype=>'A', callback=>\&mDNS::mDNS_dumpResult}) }
'normale'
mdns ipv4 namensauflösung für <hostname> d.h. für hostname.local
{ mDNS::mDNS_Lookup({qname=>'<hostname>', qtype=>'AAAA', callback=>\&mDNS::mDNS_dumpResult}) }
das gleiche für
ipv6{ mDNS::mDNS_Lookup({qname=>'<hostname>', qtype=>'ALL',singlerr=>1,callback=>\&mDNS::mDNS_dumpResult}) }
die erste antwort für <hostname> egal ob v4 oder v6
statt mDNS::mDNS_dumpResult um das ergebnis nur ins log zu schreiben ist natürlich für eine sinnvolle verwendung eigener code als callback anzugeben.
die geplanten nächsten schritte sind: den multicast mode inklusive im hintergrund laufendem daten sammeln modul aufräumen und posten, die gesammelten daten dann im discovery modul verwenden, um auch upnp/ssdp im discovery modul zu verwenden irgendwie meine version von upnp/ssdp mit dem neuen modul aus dem upnp thread unter einen hut bringen.