mirror of
https://github.com/yggdrasil-network/yggdrasil-go.git
synced 2025-04-28 22:25:07 +03:00
Refactor multicast so that it creates a new TCP listener for each interface with LL addresses (so that it will not break if Listen is not set with a wildcard address)
This commit is contained in:
parent
2419b61b2c
commit
de2aff2758
3 changed files with 68 additions and 50 deletions
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/ipv6"
|
||||
|
@ -16,19 +15,16 @@ type multicast struct {
|
|||
reconfigure chan chan error
|
||||
sock *ipv6.PacketConn
|
||||
groupAddr string
|
||||
myAddr *net.TCPAddr
|
||||
myAddrMutex sync.RWMutex
|
||||
listeners map[string]*tcpListener
|
||||
}
|
||||
|
||||
func (m *multicast) init(core *Core) {
|
||||
m.core = core
|
||||
m.reconfigure = make(chan chan error, 1)
|
||||
m.listeners = make(map[string]*tcpListener)
|
||||
go func() {
|
||||
for {
|
||||
e := <-m.reconfigure
|
||||
m.myAddrMutex.Lock()
|
||||
m.myAddr = m.core.link.tcp.getAddr()
|
||||
m.myAddrMutex.Unlock()
|
||||
e <- nil
|
||||
}
|
||||
}()
|
||||
|
@ -94,10 +90,12 @@ func (m *multicast) interfaces() []net.Interface {
|
|||
continue
|
||||
}
|
||||
for _, expr := range exprs {
|
||||
// Compile each regular expression
|
||||
e, err := regexp.Compile(expr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Does the interface match the regular expression? Store it if so
|
||||
if e.MatchString(iface.Name) {
|
||||
interfaces = append(interfaces, iface)
|
||||
}
|
||||
|
@ -107,10 +105,6 @@ func (m *multicast) interfaces() []net.Interface {
|
|||
}
|
||||
|
||||
func (m *multicast) announce() {
|
||||
var anAddr net.TCPAddr
|
||||
m.myAddrMutex.Lock()
|
||||
m.myAddr = m.core.link.tcp.getAddr()
|
||||
m.myAddrMutex.Unlock()
|
||||
groupAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -121,27 +115,47 @@ func (m *multicast) announce() {
|
|||
}
|
||||
for {
|
||||
for _, iface := range m.interfaces() {
|
||||
m.sock.JoinGroup(&iface, groupAddr)
|
||||
// Find interface addresses
|
||||
addrs, err := iface.Addrs()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
m.myAddrMutex.RLock()
|
||||
anAddr.Port = m.myAddr.Port
|
||||
m.myAddrMutex.RUnlock()
|
||||
for _, addr := range addrs {
|
||||
addrIP, _, _ := net.ParseCIDR(addr.String())
|
||||
// Ignore IPv4 addresses
|
||||
if addrIP.To4() != nil {
|
||||
continue
|
||||
} // IPv6 only
|
||||
}
|
||||
// Ignore non-link-local addresses
|
||||
if !addrIP.IsLinkLocalUnicast() {
|
||||
continue
|
||||
}
|
||||
anAddr.IP = addrIP
|
||||
anAddr.Zone = iface.Name
|
||||
destAddr.Zone = iface.Name
|
||||
msg := []byte(anAddr.String())
|
||||
m.sock.WriteTo(msg, nil, destAddr)
|
||||
// Join the multicast group
|
||||
m.sock.JoinGroup(&iface, groupAddr)
|
||||
// Try and see if we already have a TCP listener for this interface
|
||||
var listener *tcpListener
|
||||
if _, ok := m.listeners[iface.Name]; !ok {
|
||||
// No listener was found - let's create one
|
||||
listenaddr := fmt.Sprintf("[%s%%%s]:0", addrIP, iface.Name)
|
||||
if l, err := m.core.link.tcp.listen(listenaddr); err == nil {
|
||||
// Store the listener so that we can stop it later if needed
|
||||
listener = &tcpListener{
|
||||
listener: l,
|
||||
stop: make(chan bool),
|
||||
}
|
||||
m.listeners[iface.Name] = listener
|
||||
}
|
||||
} else {
|
||||
// An existing listener was found
|
||||
listener = m.listeners[iface.Name]
|
||||
}
|
||||
// Get the listener details and construct the multicast beacon
|
||||
lladdr := (*listener.listener).Addr().String()
|
||||
if a, err := net.ResolveTCPAddr("tcp6", lladdr); err == nil {
|
||||
destAddr.Zone = iface.Name
|
||||
msg := []byte(a.String())
|
||||
m.sock.WriteTo(msg, nil, destAddr)
|
||||
}
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue