Use a socket per interface for v6 multicast (fixes #1563)
This commit is contained in:
parent
207b43499c
commit
221f43e4bd
@ -16,7 +16,7 @@ type Broadcast struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewBroadcast(port int) (*Broadcast, error) {
|
func NewBroadcast(port int) (*Broadcast, error) {
|
||||||
conn, err := net.ListenUDP("udp", &net.UDPAddr{Port: port})
|
conn, err := net.ListenUDP("udp4", &net.UDPAddr{Port: port})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,22 +11,28 @@ import "net"
|
|||||||
type Multicast struct {
|
type Multicast struct {
|
||||||
conn *net.UDPConn
|
conn *net.UDPConn
|
||||||
addr *net.UDPAddr
|
addr *net.UDPAddr
|
||||||
|
intf *net.Interface
|
||||||
inbox chan []byte
|
inbox chan []byte
|
||||||
outbox chan recv
|
outbox chan recv
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMulticast(addr string) (*Multicast, error) {
|
func NewMulticast(addr, ifname string) (*Multicast, error) {
|
||||||
gaddr, err := net.ResolveUDPAddr("udp", addr)
|
gaddr, err := net.ResolveUDPAddr("udp6", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
conn, err := net.ListenMulticastUDP("udp", nil, gaddr)
|
intf, err := net.InterfaceByName(ifname)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
conn, err := net.ListenMulticastUDP("udp6", intf, gaddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
b := &Multicast{
|
b := &Multicast{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
addr: gaddr,
|
addr: gaddr,
|
||||||
|
intf: intf,
|
||||||
inbox: make(chan []byte),
|
inbox: make(chan []byte),
|
||||||
outbox: make(chan recv, 16),
|
outbox: make(chan recv, 16),
|
||||||
}
|
}
|
||||||
@ -47,27 +53,14 @@ func (b *Multicast) Recv() ([]byte, net.Addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (b *Multicast) writer() {
|
func (b *Multicast) writer() {
|
||||||
for bs := range b.inbox {
|
|
||||||
intfs, err := net.Interfaces()
|
|
||||||
if err != nil {
|
|
||||||
if debug {
|
|
||||||
l.Debugln("multicast interfaces:", err)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, intf := range intfs {
|
|
||||||
if intf.Flags&net.FlagUp != 0 && intf.Flags&net.FlagMulticast != 0 {
|
|
||||||
addr := *b.addr
|
addr := *b.addr
|
||||||
addr.Zone = intf.Name
|
addr.Zone = b.intf.Name
|
||||||
_, err = b.conn.WriteTo(bs, &addr)
|
for bs := range b.inbox {
|
||||||
if err != nil {
|
_, err := b.conn.WriteTo(bs, &addr)
|
||||||
if debug {
|
if err != nil && debug {
|
||||||
l.Debugln(err, "on write to", addr)
|
l.Debugln(err, "on write to", addr)
|
||||||
}
|
|
||||||
} else if debug {
|
} else if debug {
|
||||||
l.Debugf("sent %d bytes to %s", len(bs), addr.String())
|
l.Debugf("sent %d bytes to %s", len(bs), addr.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,8 +28,7 @@ type Discoverer struct {
|
|||||||
localBcastStart time.Time
|
localBcastStart time.Time
|
||||||
cacheLifetime time.Duration
|
cacheLifetime time.Duration
|
||||||
negCacheCutoff time.Duration
|
negCacheCutoff time.Duration
|
||||||
broadcastBeacon beacon.Interface
|
beacons []beacon.Interface
|
||||||
multicastBeacon beacon.Interface
|
|
||||||
extPort uint16
|
extPort uint16
|
||||||
localBcastTick <-chan time.Time
|
localBcastTick <-chan time.Time
|
||||||
forcedBcastTick chan time.Time
|
forcedBcastTick chan time.Time
|
||||||
@ -65,38 +64,69 @@ func NewDiscoverer(id protocol.DeviceID, addresses []string) *Discoverer {
|
|||||||
|
|
||||||
func (d *Discoverer) StartLocal(localPort int, localMCAddr string) {
|
func (d *Discoverer) StartLocal(localPort int, localMCAddr string) {
|
||||||
if localPort > 0 {
|
if localPort > 0 {
|
||||||
|
d.startLocalIPv4Broadcasts(localPort)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(localMCAddr) > 0 {
|
||||||
|
d.startLocalIPv6Multicasts(localMCAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(d.beacons) == 0 {
|
||||||
|
l.Warnln("Local discovery unavailable")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
d.localBcastTick = time.Tick(d.localBcastIntv)
|
||||||
|
d.forcedBcastTick = make(chan time.Time)
|
||||||
|
d.localBcastStart = time.Now()
|
||||||
|
go d.sendLocalAnnouncements()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Discoverer) startLocalIPv4Broadcasts(localPort int) {
|
||||||
bb, err := beacon.NewBroadcast(localPort)
|
bb, err := beacon.NewBroadcast(localPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if debug {
|
if debug {
|
||||||
l.Debugln("discover: Start local v4:", err)
|
l.Debugln("discover: Start local v4:", err)
|
||||||
}
|
}
|
||||||
l.Infoln("Local discovery over IPv4 unavailable")
|
l.Infoln("Local discovery over IPv4 unavailable")
|
||||||
} else {
|
return
|
||||||
d.broadcastBeacon = bb
|
|
||||||
go d.recvAnnouncements(bb)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(localMCAddr) > 0 {
|
d.beacons = append(d.beacons, bb)
|
||||||
mb, err := beacon.NewMulticast(localMCAddr)
|
go d.recvAnnouncements(bb)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Discoverer) startLocalIPv6Multicasts(localMCAddr string) {
|
||||||
|
intfs, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
if debug {
|
||||||
|
l.Debugln("discover: interfaces:", err)
|
||||||
|
}
|
||||||
|
l.Infoln("Local discovery over IPv6 unavailable")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
v6Intfs := 0
|
||||||
|
for _, intf := range intfs {
|
||||||
|
if intf.Flags&net.FlagUp == 0 || intf.Flags&net.FlagMulticast == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
mb, err := beacon.NewMulticast(localMCAddr, intf.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if debug {
|
if debug {
|
||||||
l.Debugln("discover: Start local v6:", err)
|
l.Debugln("discover: Start local v6:", err)
|
||||||
}
|
}
|
||||||
l.Infoln("Local discovery over IPv6 unavailable")
|
continue
|
||||||
} else {
|
|
||||||
d.multicastBeacon = mb
|
|
||||||
go d.recvAnnouncements(mb)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.broadcastBeacon == nil && d.multicastBeacon == nil {
|
d.beacons = append(d.beacons, mb)
|
||||||
l.Warnln("Local discovery unavailable")
|
go d.recvAnnouncements(mb)
|
||||||
} else {
|
v6Intfs++
|
||||||
d.localBcastTick = time.Tick(d.localBcastIntv)
|
}
|
||||||
d.forcedBcastTick = make(chan time.Time)
|
|
||||||
d.localBcastStart = time.Now()
|
if v6Intfs == 0 {
|
||||||
go d.sendLocalAnnouncements()
|
l.Infoln("Local discovery over IPv6 unavailable")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,11 +318,8 @@ func (d *Discoverer) sendLocalAnnouncements() {
|
|||||||
msg := pkt.MustMarshalXDR()
|
msg := pkt.MustMarshalXDR()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if d.multicastBeacon != nil {
|
for _, b := range d.beacons {
|
||||||
d.multicastBeacon.Send(msg)
|
b.Send(msg)
|
||||||
}
|
|
||||||
if d.broadcastBeacon != nil {
|
|
||||||
d.broadcastBeacon.Send(msg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user