From eba0750cb91e780a2c1e44d8c8b753d1a118d351 Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Tue, 27 Jan 2026 22:11:42 -0800 Subject: [PATCH] Bind send interface for sacn --- main.go | 3 ++- sacn/sender.go | 18 ++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/main.go b/main.go index 1012745..acc0d05 100644 --- a/main.go +++ b/main.go @@ -34,6 +34,7 @@ func main() { configPath := flag.String("config", "config.toml", "path to config file") artnetListen := flag.String("artnet-listen", ":6454", "artnet listen address (empty to disable)") artnetBroadcast := flag.String("artnet-broadcast", "auto", "artnet broadcast addresses (comma-separated, or 'auto')") + sacnInterface := flag.String("sacn-interface", "", "network interface for sACN multicast") debug := flag.Bool("debug", false, "log incoming/outgoing dmx packets") flag.Parse() @@ -107,7 +108,7 @@ func main() { defer artSender.Close() // Create sACN sender - sacnSender, err := sacn.NewSender("artmap") + sacnSender, err := sacn.NewSender("artmap", *sacnInterface) if err != nil { log.Fatalf("sacn sender error: %v", err) } diff --git a/sacn/sender.go b/sacn/sender.go index 9cc8ff9..7f75aae 100644 --- a/sacn/sender.go +++ b/sacn/sender.go @@ -4,6 +4,8 @@ import ( "crypto/rand" "net" "sync" + + "golang.org/x/net/ipv4" ) // Sender sends sACN (E1.31) packets @@ -16,13 +18,25 @@ type Sender struct { } // NewSender creates a new sACN sender -func NewSender(sourceName string) (*Sender, error) { +func NewSender(sourceName string, ifaceName string) (*Sender, error) { conn, err := net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0}) if err != nil { return nil, err } - // Generate random CID + if ifaceName != "" { + iface, err := net.InterfaceByName(ifaceName) + if err != nil { + conn.Close() + return nil, err + } + p := ipv4.NewPacketConn(conn) + if err := p.SetMulticastInterface(iface); err != nil { + conn.Close() + return nil, err + } + } + var cid [16]byte rand.Read(cid[:])