Fix ArtPollReply to send to broadcast:6454 with proper MAC detection
This commit is contained in:
@@ -21,9 +21,12 @@ type Node struct {
|
|||||||
// Discovery handles ArtNet node discovery
|
// Discovery handles ArtNet node discovery
|
||||||
type Discovery struct {
|
type Discovery struct {
|
||||||
sender *Sender
|
sender *Sender
|
||||||
|
receiver *Receiver
|
||||||
nodes map[string]*Node // keyed by IP string
|
nodes map[string]*Node // keyed by IP string
|
||||||
nodesMu sync.RWMutex
|
nodesMu sync.RWMutex
|
||||||
localIP [4]byte
|
localIP [4]byte
|
||||||
|
localMAC [6]byte
|
||||||
|
broadcast net.IP
|
||||||
shortName string
|
shortName string
|
||||||
longName string
|
longName string
|
||||||
inputUnivs []Universe // universes we transmit TO (SwIn)
|
inputUnivs []Universe // universes we transmit TO (SwIn)
|
||||||
@@ -48,10 +51,7 @@ func NewDiscovery(sender *Sender, shortName, longName string, inputUnivs, output
|
|||||||
|
|
||||||
// Start begins periodic discovery
|
// Start begins periodic discovery
|
||||||
func (d *Discovery) Start() {
|
func (d *Discovery) Start() {
|
||||||
// Get local IP
|
d.detectInterface()
|
||||||
d.localIP = d.getLocalIP()
|
|
||||||
|
|
||||||
// Start periodic poll
|
|
||||||
go d.pollLoop()
|
go d.pollLoop()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,8 +187,9 @@ func (d *Discovery) HandlePollReply(src *net.UDPAddr, pkt *PollReplyPacket) {
|
|||||||
|
|
||||||
// HandlePoll processes an incoming ArtPoll and responds
|
// HandlePoll processes an incoming ArtPoll and responds
|
||||||
func (d *Discovery) HandlePoll(src *net.UDPAddr) {
|
func (d *Discovery) HandlePoll(src *net.UDPAddr) {
|
||||||
d.sendPollReplies(src, d.inputUnivs, true)
|
dst := &net.UDPAddr{IP: d.broadcast, Port: Port}
|
||||||
d.sendPollReplies(src, d.outputUnivs, false)
|
d.sendPollReplies(dst, d.inputUnivs, true)
|
||||||
|
d.sendPollReplies(dst, d.outputUnivs, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Discovery) sendPollReplies(dst *net.UDPAddr, universes []Universe, isInput bool) {
|
func (d *Discovery) sendPollReplies(dst *net.UDPAddr, universes []Universe, isInput bool) {
|
||||||
@@ -205,7 +206,9 @@ func (d *Discovery) sendPollReplies(dst *net.UDPAddr, universes []Universe, isIn
|
|||||||
end = len(univs)
|
end = len(univs)
|
||||||
}
|
}
|
||||||
chunk := univs[i:end]
|
chunk := univs[i:end]
|
||||||
err := d.sender.SendPollReply(dst, d.localIP, d.shortName, d.longName, chunk, isInput)
|
|
||||||
|
pkt := BuildPollReplyPacket(d.localIP, d.localMAC, d.shortName, d.longName, chunk, isInput)
|
||||||
|
err := d.receiver.SendTo(pkt, dst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[->artnet] pollreply error: dst=%s err=%v", dst.IP, err)
|
log.Printf("[->artnet] pollreply error: dst=%s err=%v", dst.IP, err)
|
||||||
}
|
}
|
||||||
@@ -250,24 +253,50 @@ func (d *Discovery) GetAllNodes() []*Node {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Discovery) getLocalIP() [4]byte {
|
func (d *Discovery) detectInterface() {
|
||||||
var result [4]byte
|
d.broadcast = net.IPv4bcast
|
||||||
|
|
||||||
addrs, err := net.InterfaceAddrs()
|
ifaces, err := net.Interfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, addr := range addrs {
|
for _, iface := range ifaces {
|
||||||
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
|
if iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagUp == 0 {
|
||||||
if ip4 := ipnet.IP.To4(); ip4 != nil {
|
continue
|
||||||
copy(result[:], ip4)
|
}
|
||||||
return result
|
|
||||||
|
addrs, err := iface.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
ipnet, ok := addr.(*net.IPNet)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ip4 := ipnet.IP.To4()
|
||||||
|
if ip4 == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(d.localIP[:], ip4)
|
||||||
|
|
||||||
|
if len(iface.HardwareAddr) == 6 {
|
||||||
|
copy(d.localMAC[:], iface.HardwareAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
bcast := make(net.IP, 4)
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
bcast[i] = ip4[i] | ^ipnet.Mask[i]
|
||||||
|
}
|
||||||
|
d.broadcast = bcast
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLocalIP sets the local IP for PollReply responses
|
// SetLocalIP sets the local IP for PollReply responses
|
||||||
@@ -276,3 +305,8 @@ func (d *Discovery) SetLocalIP(ip net.IP) {
|
|||||||
copy(d.localIP[:], ip4)
|
copy(d.localIP[:], ip4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetReceiver sets the receiver for sending poll replies from port 6454
|
||||||
|
func (d *Discovery) SetReceiver(r *Receiver) {
|
||||||
|
d.receiver = r
|
||||||
|
}
|
||||||
|
|||||||
@@ -255,8 +255,8 @@ func BuildPollPacket() []byte {
|
|||||||
|
|
||||||
// BuildPollReplyPacket creates an ArtPollReply packet
|
// BuildPollReplyPacket creates an ArtPollReply packet
|
||||||
// isInput: true = we transmit to network (SwIn), false = we receive from network (SwOut)
|
// isInput: true = we transmit to network (SwIn), false = we receive from network (SwOut)
|
||||||
func BuildPollReplyPacket(ip [4]byte, shortName, longName string, universes []Universe, isInput bool) []byte {
|
func BuildPollReplyPacket(ip [4]byte, mac [6]byte, shortName, longName string, universes []Universe, isInput bool) []byte {
|
||||||
buf := make([]byte, 239)
|
buf := make([]byte, 240)
|
||||||
|
|
||||||
copy(buf[0:8], ArtNetID[:])
|
copy(buf[0:8], ArtNetID[:])
|
||||||
binary.LittleEndian.PutUint16(buf[8:10], OpPollReply)
|
binary.LittleEndian.PutUint16(buf[8:10], OpPollReply)
|
||||||
@@ -280,17 +280,20 @@ func BuildPollReplyPacket(ip [4]byte, shortName, longName string, universes []Un
|
|||||||
|
|
||||||
for i := 0; i < numPorts; i++ {
|
for i := 0; i < numPorts; i++ {
|
||||||
if isInput {
|
if isInput {
|
||||||
buf[174+i] = 0x40 // Can input to Art-Net (we transmit)
|
buf[174+i] = 0x40
|
||||||
buf[178+i] = 0x80 // Data received
|
buf[178+i] = 0x80
|
||||||
buf[186+i] = universes[i].Universe()
|
buf[186+i] = universes[i].Universe()
|
||||||
} else {
|
} else {
|
||||||
buf[174+i] = 0x80 // Can output from Art-Net (we receive)
|
buf[174+i] = 0x80
|
||||||
buf[182+i] = 0x80 // Data transmitted
|
buf[182+i] = 0x80
|
||||||
buf[190+i] = universes[i].Universe()
|
buf[190+i] = universes[i].Universe()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[200] = 0x00 // StNode
|
copy(buf[201:207], mac[:])
|
||||||
|
copy(buf[207:211], ip[:])
|
||||||
|
buf[211] = 1
|
||||||
|
buf[212] = 0x08
|
||||||
|
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,3 +96,9 @@ func (r *Receiver) handlePacket(src *net.UDPAddr, data []byte) {
|
|||||||
func (r *Receiver) LocalAddr() net.Addr {
|
func (r *Receiver) LocalAddr() net.Addr {
|
||||||
return r.conn.LocalAddr()
|
return r.conn.LocalAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SendTo sends a raw packet through the receiver's socket (port 6454)
|
||||||
|
func (r *Receiver) SendTo(data []byte, addr *net.UDPAddr) error {
|
||||||
|
_, err := r.conn.WriteToUDP(data, addr)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,13 +55,6 @@ func (s *Sender) SendPoll(addr *net.UDPAddr) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendPollReply sends an ArtPollReply to a specific address
|
|
||||||
func (s *Sender) SendPollReply(addr *net.UDPAddr, localIP [4]byte, shortName, longName string, universes []Universe, isInput bool) error {
|
|
||||||
pkt := BuildPollReplyPacket(localIP, shortName, longName, universes, isInput)
|
|
||||||
_, err := s.conn.WriteToUDP(pkt, addr)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the sender
|
// Close closes the sender
|
||||||
func (s *Sender) Close() error {
|
func (s *Sender) Close() error {
|
||||||
return s.conn.Close()
|
return s.conn.Close()
|
||||||
|
|||||||
1
main.go
1
main.go
@@ -149,6 +149,7 @@ func main() {
|
|||||||
log.Fatalf("artnet receiver error: %v", err)
|
log.Fatalf("artnet receiver error: %v", err)
|
||||||
}
|
}
|
||||||
app.artReceiver = artReceiver
|
app.artReceiver = artReceiver
|
||||||
|
discovery.SetReceiver(artReceiver)
|
||||||
artReceiver.Start()
|
artReceiver.Start()
|
||||||
log.Printf("[artnet] listening addr=%s", addr)
|
log.Printf("[artnet] listening addr=%s", addr)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user