Skip to content

Commit f13d823

Browse files
committed
Improve network interface handling for multicast send and receive
1 parent 6ac4fd9 commit f13d823

File tree

2 files changed

+59
-10
lines changed

2 files changed

+59
-10
lines changed

internal/app/publish/publisher.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,19 @@ func (p *Publisher) disconnect() {
7979
p.conns = []*net.UDPConn{}
8080
}
8181

82+
func (p *Publisher) disconnectConn(conn *net.UDPConn) {
83+
if err := conn.Close(); err != nil {
84+
log.Println("Failed to close referee connection:", err)
85+
}
86+
87+
for i, c := range p.conns {
88+
if c == conn {
89+
p.conns = append(p.conns[:i], p.conns[i+1:]...)
90+
break
91+
}
92+
}
93+
}
94+
8295
func (p *Publisher) SendMessage(refereeMsg *state.Referee) {
8396
if len(p.conns) == 0 && !p.connect() {
8497
return
@@ -88,8 +101,8 @@ func (p *Publisher) SendMessage(refereeMsg *state.Referee) {
88101
for _, conn := range p.conns {
89102
_, err = conn.Write(bytes)
90103
if err != nil {
91-
log.Println("Could not write referee message:", err)
92-
p.disconnect()
104+
log.Printf("Could not write referee message on %v: %v", conn, err)
105+
p.disconnectConn(conn)
93106
}
94107
}
95108
}

pkg/sslnet/multicast_server.go

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package sslnet
33
import (
44
"log"
55
"net"
6+
"net/netip"
67
"sync"
78
"time"
89
)
@@ -40,11 +41,20 @@ func (r *MulticastServer) Stop() {
4041

4142
func (r *MulticastServer) receive(multicastAddress string) {
4243
var currentIfiIdx = 0
44+
var badIfis []string
4345
for r.isRunning() {
44-
ifis := r.interfaces()
46+
ifis := r.interfaces(badIfis)
47+
if len(ifis) == 0 {
48+
log.Println("No valid interfaces found to listen on")
49+
return
50+
}
4551
currentIfiIdx = currentIfiIdx % len(ifis)
4652
ifi := ifis[currentIfiIdx]
47-
r.receiveOnInterface(multicastAddress, ifi)
53+
badIfi := r.receiveOnInterface(multicastAddress, ifi)
54+
if badIfi {
55+
badIfis = append(badIfis, ifi.Name)
56+
}
57+
4858
currentIfiIdx++
4959
if currentIfiIdx >= len(ifis) {
5060
// cycled though all interfaces once, make a short break to avoid producing endless log messages
@@ -59,41 +69,65 @@ func (r *MulticastServer) isRunning() bool {
5969
return r.running
6070
}
6171

62-
func (r *MulticastServer) interfaces() (interfaces []net.Interface) {
72+
func (r *MulticastServer) interfaces(ignoreIfis []string) (interfaces []net.Interface) {
6373
interfaces = []net.Interface{}
6474
ifis, err := net.Interfaces()
6575
if err != nil {
6676
log.Println("Could not get available interfaces: ", err)
6777
}
6878
for _, ifi := range ifis {
6979
if ifi.Flags&net.FlagMulticast == 0 || // No multicast support
70-
r.skipInterface(ifi.Name) {
80+
ifi.Flags&net.FlagUp == 0 || // Not up
81+
ifi.Flags&net.FlagRunning == 0 || // Not running
82+
r.skipInterface(r.SkipInterfaces, ifi.Name) ||
83+
r.skipInterface(ignoreIfis, ifi.Name) ||
84+
isInvalidInterface(&ifi) {
7185
continue
7286
}
7387
interfaces = append(interfaces, ifi)
7488
}
7589
return
7690
}
7791

78-
func (r *MulticastServer) skipInterface(ifiName string) bool {
79-
for _, skipIfi := range r.SkipInterfaces {
92+
func isInvalidInterface(ifi *net.Interface) bool {
93+
addrs, err := ifi.Addrs()
94+
if err != nil {
95+
log.Printf("Could not get addresses of interface %v: %v", ifi, err)
96+
return false
97+
}
98+
for _, addr := range addrs {
99+
ipNet := addr.(*net.IPNet)
100+
ip := netip.MustParseAddr(ipNet.IP.String())
101+
if ip.Is4() {
102+
return false
103+
}
104+
}
105+
return true
106+
}
107+
108+
func (r *MulticastServer) skipInterface(ifis []string, ifiName string) bool {
109+
for _, skipIfi := range ifis {
80110
if skipIfi == ifiName {
81111
return true
82112
}
83113
}
84114
return false
85115
}
86116

87-
func (r *MulticastServer) receiveOnInterface(multicastAddress string, ifi net.Interface) {
117+
func (r *MulticastServer) receiveOnInterface(multicastAddress string, ifi net.Interface) (badIfi bool) {
118+
badIfi = false
119+
88120
addr, err := net.ResolveUDPAddr("udp", multicastAddress)
89121
if err != nil {
90122
log.Printf("Could resolve multicast address %v: %v", multicastAddress, err)
123+
badIfi = true
91124
return
92125
}
93126

94127
r.connection, err = net.ListenMulticastUDP("udp", &ifi, addr)
95128
if err != nil {
96-
log.Printf("Could not listen at %v: %v", multicastAddress, err)
129+
log.Printf("Could not listen at %v (%v): %v", multicastAddress, ifi.Name, err)
130+
badIfi = true
97131
return
98132
}
99133

@@ -109,6 +143,7 @@ func (r *MulticastServer) receiveOnInterface(multicastAddress string, ifi net.In
109143
data := make([]byte, maxDatagramSize)
110144
for {
111145
if err := r.connection.SetDeadline(time.Now().Add(300 * time.Millisecond)); err != nil {
146+
badIfi = true
112147
log.Println("Could not set deadline on connection: ", err)
113148
}
114149
n, _, err := r.connection.ReadFromUDP(data)
@@ -132,6 +167,7 @@ func (r *MulticastServer) receiveOnInterface(multicastAddress string, ifi net.In
132167
}
133168

134169
if err := r.connection.Close(); err != nil {
170+
badIfi = true
135171
log.Println("Could not close listener: ", err)
136172
}
137173
return

0 commit comments

Comments
 (0)