From f3b85fc8f23baeb0b1a6ef47b341cdd0a9c2656d Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Fri, 23 Jan 2026 09:12:09 -0800 Subject: [PATCH] add skaarhoj device discovery and remove unused dante query Co-Authored-By: Claude Opus 4.5 --- dante.go | 1 - mdns.go | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/dante.go b/dante.go index 578d56a..2481499 100644 --- a/dante.go +++ b/dante.go @@ -59,7 +59,6 @@ func (t *Tendrils) sendDanteMDNSQuery(ifaceName string, srcIP net.IP) { "_netaudio-dbc._udp.local.", "_netaudio-chan._udp.local.", "_dantevideo._udp.local.", - "_dantevid-flow._udp.local.", "_danteancil._udp.local.", } diff --git a/mdns.go b/mdns.go index fcdf34b..f87f470 100644 --- a/mdns.go +++ b/mdns.go @@ -35,6 +35,18 @@ func isDanteService(s string) bool { return strings.Contains(s, "_netaudio-") || strings.Contains(s, "._dante") } +func isSkaarhojService(s string) bool { + return strings.Contains(s, "_skaarhoj._tcp") +} + +func extractSkaarhojName(s string) string { + idx := strings.Index(s, "._skaarhoj._tcp") + if idx <= 0 { + return "" + } + return strings.ReplaceAll(s[:idx], "\\", "") +} + func (t *Tendrils) listenMDNS(ctx context.Context, iface net.Interface) { addr, err := net.ResolveUDPAddr("udp4", mdnsAddr) if err != nil { @@ -95,6 +107,7 @@ func (t *Tendrils) processMDNSResponse(ifaceName string, srcIP net.IP, msg *dns. aRecords := map[string]net.IP{} srvTargets := map[string]string{} danteNames := map[string]bool{} + skaarhojNames := map[string]bool{} for _, rr := range allRecords { switch r := rr.(type) { @@ -110,10 +123,16 @@ func (t *Tendrils) processMDNSResponse(ifaceName string, srcIP net.IP, msg *dns. danteNames[name] = true } } + if isSkaarhojService(r.Ptr) { + name := extractSkaarhojName(r.Ptr) + if name != "" { + skaarhojNames[name] = true + } + } case *dns.SRV: + target := strings.TrimSuffix(r.Target, ".") if isDanteService(r.Hdr.Name) { name := extractDanteName(r.Hdr.Name) - target := strings.TrimSuffix(r.Target, ".") if name != "" { danteNames[name] = true if target != "" { @@ -121,6 +140,15 @@ func (t *Tendrils) processMDNSResponse(ifaceName string, srcIP net.IP, msg *dns. } } } + if isSkaarhojService(r.Hdr.Name) { + name := extractSkaarhojName(r.Hdr.Name) + if name != "" { + skaarhojNames[name] = true + if target != "" { + srvTargets[name] = target + } + } + } } } @@ -138,7 +166,21 @@ func (t *Tendrils) processMDNSResponse(ifaceName string, srcIP net.IP, msg *dns. t.nodes.UpdateDante(name, ip) } - if len(danteNames) == 0 { + for name := range skaarhojNames { + var ip net.IP + if target, ok := srvTargets[name]; ok { + ip = aRecords[target] + } + if ip == nil { + ip = srcIP + } + if t.DebugMDNS { + log.Printf("[mdns] %s: skaarhoj %s -> %s", ifaceName, name, ip) + } + t.nodes.Update(nil, nil, []net.IP{ip}, "", name, "skaarhoj") + } + + if len(danteNames) == 0 && len(skaarhojNames) == 0 { for aName, ip := range aRecords { hostname := strings.TrimSuffix(aName, ".local") if hostname != "" && hostname != aName {