5
0
mirror of https://github.com/cwinfo/yggdrasil-go.git synced 2024-11-26 04:51:38 +00:00

use a separate multicast beacon interval per multicast interface

This commit is contained in:
Arceliar 2019-09-20 17:42:42 -05:00
parent 1cd4b6e8dd
commit 8003ea0f3e

View File

@ -26,24 +26,28 @@ type Multicast struct {
log *log.Logger log *log.Logger
sock *ipv6.PacketConn sock *ipv6.PacketConn
groupAddr string groupAddr string
listeners map[string]*yggdrasil.TcpListener listeners map[string]*listenerInfo
listenPort uint16 listenPort uint16
isOpen bool isOpen bool
interval time.Duration
announcer *time.Timer announcer *time.Timer
platformhandler *time.Timer platformhandler *time.Timer
} }
type listenerInfo struct {
listener *yggdrasil.TcpListener
time time.Time
interval time.Duration
}
// Init prepares the multicast interface for use. // Init prepares the multicast interface for use.
func (m *Multicast) Init(core *yggdrasil.Core, state *config.NodeState, log *log.Logger, options interface{}) error { func (m *Multicast) Init(core *yggdrasil.Core, state *config.NodeState, log *log.Logger, options interface{}) error {
m.core = core m.core = core
m.config = state m.config = state
m.log = log m.log = log
m.listeners = make(map[string]*yggdrasil.TcpListener) m.listeners = make(map[string]*listenerInfo)
current := m.config.GetCurrent() current := m.config.GetCurrent()
m.listenPort = current.LinkLocalTCPPort m.listenPort = current.LinkLocalTCPPort
m.groupAddr = "[ff02::114]:9001" m.groupAddr = "[ff02::114]:9001"
m.interval = time.Second
return nil return nil
} }
@ -151,10 +155,10 @@ func (m *Multicast) announce() {
interfaces := m.Interfaces() interfaces := m.Interfaces()
// There might be interfaces that we configured listeners for but are no // There might be interfaces that we configured listeners for but are no
// longer up - if that's the case then we should stop the listeners // longer up - if that's the case then we should stop the listeners
for name, listener := range m.listeners { for name, info := range m.listeners {
// Prepare our stop function! // Prepare our stop function!
stop := func() { stop := func() {
listener.Stop() info.listener.Stop()
delete(m.listeners, name) delete(m.listeners, name)
m.log.Debugln("No longer multicasting on", name) m.log.Debugln("No longer multicasting on", name)
} }
@ -167,7 +171,7 @@ func (m *Multicast) announce() {
// It's possible that the link-local listener address has changed so if // It's possible that the link-local listener address has changed so if
// that is the case then we should clean up the interface listener // that is the case then we should clean up the interface listener
found := false found := false
listenaddr, err := net.ResolveTCPAddr("tcp6", listener.Listener.Addr().String()) listenaddr, err := net.ResolveTCPAddr("tcp6", info.listener.Listener.Addr().String())
if err != nil { if err != nil {
stop() stop()
continue continue
@ -216,43 +220,46 @@ func (m *Multicast) announce() {
// Join the multicast group // Join the multicast group
m.sock.JoinGroup(&iface, groupAddr) m.sock.JoinGroup(&iface, groupAddr)
// Try and see if we already have a TCP listener for this interface // Try and see if we already have a TCP listener for this interface
var listener *yggdrasil.TcpListener var info *listenerInfo
if l, ok := m.listeners[iface.Name]; !ok || l.Listener == nil { if nfo, ok := m.listeners[iface.Name]; !ok || nfo.listener.Listener == nil {
// No listener was found - let's create one // No listener was found - let's create one
listenaddr := fmt.Sprintf("[%s%%%s]:%d", addrIP, iface.Name, m.listenPort) listenaddr := fmt.Sprintf("[%s%%%s]:%d", addrIP, iface.Name, m.listenPort)
if li, err := m.core.ListenTCP(listenaddr); err == nil { if li, err := m.core.ListenTCP(listenaddr); err == nil {
m.log.Debugln("Started multicasting on", iface.Name) m.log.Debugln("Started multicasting on", iface.Name)
// Store the listener so that we can stop it later if needed // Store the listener so that we can stop it later if needed
m.listeners[iface.Name] = li info = &listenerInfo{listener: li, time: time.Now()}
listener = li m.listeners[iface.Name] = info
} else { } else {
m.log.Warnln("Not multicasting on", iface.Name, "due to error:", err) m.log.Warnln("Not multicasting on", iface.Name, "due to error:", err)
} }
} else { } else {
// An existing listener was found // An existing listener was found
listener = m.listeners[iface.Name] info = m.listeners[iface.Name]
} }
// Make sure nothing above failed for some reason // Make sure nothing above failed for some reason
if listener == nil { if info == nil {
continue
}
if time.Since(info.time) < info.interval {
continue continue
} }
// Get the listener details and construct the multicast beacon // Get the listener details and construct the multicast beacon
lladdr := listener.Listener.Addr().String() lladdr := info.listener.Listener.Addr().String()
if a, err := net.ResolveTCPAddr("tcp6", lladdr); err == nil { if a, err := net.ResolveTCPAddr("tcp6", lladdr); err == nil {
a.Zone = "" a.Zone = ""
destAddr.Zone = iface.Name destAddr.Zone = iface.Name
msg := []byte(a.String()) msg := []byte(a.String())
m.sock.WriteTo(msg, nil, destAddr) m.sock.WriteTo(msg, nil, destAddr)
} }
if info.interval.Seconds() < 15 {
info.interval += time.Second
}
break break
} }
} }
m.announcer = time.AfterFunc(m.interval, func() { m.announcer = time.AfterFunc(time.Second, func() {
m.Act(m, m.announce) m.Act(m, m.announce)
}) })
if m.interval.Seconds() < 15 {
m.interval += time.Second
}
} }
func (m *Multicast) listen() { func (m *Multicast) listen() {