send mdns queries from listener socket for multicast responses

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Ian Gulliver
2026-01-23 09:27:45 -08:00
parent f3b85fc8f2
commit 6394b55191
2 changed files with 29 additions and 106 deletions

View File

@@ -5,81 +5,12 @@ import (
"log"
"net"
"time"
"github.com/miekg/dns"
)
func (t *Tendrils) listenDante(ctx context.Context, iface net.Interface) {
go t.queryDanteMDNS(ctx, iface)
go t.listenPTP(ctx, iface)
}
func (t *Tendrils) queryDanteMDNS(ctx context.Context, iface net.Interface) {
addrs, err := iface.Addrs()
if err != nil {
return
}
var srcIP net.IP
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.To4() != nil {
srcIP = ipnet.IP.To4()
break
}
}
if srcIP == nil {
return
}
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
t.sendDanteMDNSQuery(iface.Name, srcIP)
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
t.sendDanteMDNSQuery(iface.Name, srcIP)
}
}
}
func (t *Tendrils) sendDanteMDNSQuery(ifaceName string, srcIP net.IP) {
conn, err := net.DialUDP("udp4", &net.UDPAddr{IP: srcIP}, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 251), Port: 5353})
if err != nil {
return
}
defer conn.Close()
services := []string{
"_netaudio-arc._udp.local.",
"_netaudio-cmc._udp.local.",
"_netaudio-dbc._udp.local.",
"_netaudio-chan._udp.local.",
"_dantevideo._udp.local.",
"_danteancil._udp.local.",
}
for _, service := range services {
msg := new(dns.Msg)
msg.SetQuestion(service, dns.TypePTR)
msg.RecursionDesired = false
data, err := msg.Pack()
if err != nil {
continue
}
conn.Write(data)
}
if t.DebugDante {
log.Printf("[dante] %s: sent mdns queries for netaudio services", ifaceName)
}
}
func (t *Tendrils) listenPTP(ctx context.Context, iface net.Interface) {
addr, err := net.ResolveUDPAddr("udp4", "224.0.1.129:319")
if err != nil {

52
mdns.go
View File

@@ -61,7 +61,7 @@ func (t *Tendrils) listenMDNS(ctx context.Context, iface net.Interface) {
}
defer conn.Close()
go t.runMDNSQuerier(ctx, iface)
go t.runMDNSQuerier(ctx, iface, conn)
buf := make([]byte, 65536)
for {
@@ -193,57 +193,49 @@ func (t *Tendrils) processMDNSResponse(ifaceName string, srcIP net.IP, msg *dns.
}
}
func (t *Tendrils) runMDNSQuerier(ctx context.Context, iface net.Interface) {
addrs, err := iface.Addrs()
if err != nil {
return
}
var mdnsServices = []string{
"_services._dns-sd._udp.local.",
"_netaudio-arc._udp.local.",
"_netaudio-cmc._udp.local.",
"_netaudio-dbc._udp.local.",
"_netaudio-chan._udp.local.",
"_dantevideo._udp.local.",
"_danteancil._udp.local.",
}
var srcIP net.IP
for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok && ipnet.IP.To4() != nil {
srcIP = ipnet.IP.To4()
break
}
}
if srcIP == nil {
return
}
ticker := time.NewTicker(60 * time.Second)
func (t *Tendrils) runMDNSQuerier(ctx context.Context, iface net.Interface, conn *net.UDPConn) {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
t.sendMDNSQuery(iface.Name, srcIP)
t.sendMDNSQueries(iface.Name, conn)
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
t.sendMDNSQuery(iface.Name, srcIP)
t.sendMDNSQueries(iface.Name, conn)
}
}
}
func (t *Tendrils) sendMDNSQuery(ifaceName string, srcIP net.IP) {
conn, err := net.DialUDP("udp4", &net.UDPAddr{IP: srcIP}, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 251), Port: 5353})
if err != nil {
return
}
defer conn.Close()
func (t *Tendrils) sendMDNSQueries(ifaceName string, conn *net.UDPConn) {
dest := &net.UDPAddr{IP: net.IPv4(224, 0, 0, 251), Port: 5353}
for _, service := range mdnsServices {
msg := new(dns.Msg)
msg.SetQuestion("_services._dns-sd._udp.local.", dns.TypePTR)
msg.SetQuestion(service, dns.TypePTR)
msg.RecursionDesired = false
data, err := msg.Pack()
if err != nil {
return
continue
}
conn.Write(data)
conn.WriteToUDP(data, dest)
}
if t.DebugMDNS {
log.Printf("[mdns] %s: sent query", ifaceName)
log.Printf("[mdns] %s: sent queries for %d services", ifaceName, len(mdnsServices))
}
}