Implement IPv6 multicast again (fixes #346)

This commit is contained in:
Jakob Borg
2014-08-17 15:01:48 +02:00
parent a1fd07b27c
commit d657bc4e3d
9 changed files with 151 additions and 52 deletions

46
beacon/beacon.go Normal file
View File

@@ -0,0 +1,46 @@
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
// All rights reserved. Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package beacon
import "net"
type recv struct {
data []byte
src net.Addr
}
type dst struct {
intf string
conn *net.UDPConn
}
type Interface interface {
Send(data []byte)
Recv() ([]byte, net.Addr)
}
func genericReader(conn *net.UDPConn, outbox chan<- recv) {
bs := make([]byte, 65536)
for {
n, addr, err := conn.ReadFrom(bs)
if err != nil {
l.Warnln("multicast read:", err)
return
}
if debug {
l.Debugf("recv %d bytes from %s", n, addr)
}
c := make([]byte, n)
copy(c, bs)
select {
case outbox <- recv{c, addr}:
default:
if debug {
l.Debugln("dropping message")
}
}
}
}

View File

@@ -6,16 +6,6 @@ package beacon
import "net"
type recv struct {
data []byte
src net.Addr
}
type dst struct {
intf string
conn *net.UDPConn
}
type Broadcast struct {
conn *net.UDPConn
port int
@@ -36,7 +26,7 @@ func NewBroadcast(port int) (*Broadcast, error) {
outbox: make(chan recv, 16),
}
go b.reader()
go genericReader(b.conn, b.outbox)
go b.writer()
return b, nil
@@ -51,30 +41,6 @@ func (b *Broadcast) Recv() ([]byte, net.Addr) {
return recv.data, recv.src
}
func (b *Broadcast) reader() {
bs := make([]byte, 65536)
for {
n, addr, err := b.conn.ReadFrom(bs)
if err != nil {
l.Warnln("Broadcast read:", err)
return
}
if debug {
l.Debugf("recv %d bytes from %s", n, addr)
}
c := make([]byte, n)
copy(c, bs)
select {
case b.outbox <- recv{c, addr}:
default:
if debug {
l.Debugln("dropping message")
}
}
}
}
func (b *Broadcast) writer() {
for bs := range b.inbox {

70
beacon/multicast.go Normal file
View File

@@ -0,0 +1,70 @@
// Copyright (C) 2014 Jakob Borg and Contributors (see the CONTRIBUTORS file).
// All rights reserved. Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package beacon
import "net"
type Multicast struct {
conn *net.UDPConn
addr *net.UDPAddr
conns []dst
inbox chan []byte
outbox chan recv
}
func NewMulticast(addr string) (*Multicast, error) {
gaddr, err := net.ResolveUDPAddr("udp", addr)
if err != nil {
return nil, err
}
conn, err := net.ListenMulticastUDP("udp", nil, gaddr)
if err != nil {
return nil, err
}
b := &Multicast{
conn: conn,
addr: gaddr,
inbox: make(chan []byte),
outbox: make(chan recv, 16),
}
go genericReader(b.conn, b.outbox)
go b.writer()
return b, nil
}
func (b *Multicast) Send(data []byte) {
b.inbox <- data
}
func (b *Multicast) Recv() ([]byte, net.Addr) {
recv := <-b.outbox
return recv.data, recv.src
}
func (b *Multicast) writer() {
for bs := range b.inbox {
intfs, err := net.Interfaces()
if err != nil {
l.Warnln("multicast interfaces:", err)
continue
}
for _, intf := range intfs {
if intf.Flags&net.FlagUp != 0 && intf.Flags&net.FlagMulticast != 0 {
addr := *b.addr
addr.Zone = intf.Name
_, err = b.conn.WriteTo(bs, &addr)
if err != nil {
if debug {
l.Debugln(err, "on write to", addr)
}
} else if debug {
l.Debugf("sent %d bytes to %s", len(bs), addr.String())
}
}
}
}
}