diff options
Diffstat (limited to 'mc/beacon.go')
-rw-r--r-- | mc/beacon.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/mc/beacon.go b/mc/beacon.go new file mode 100644 index 0000000000..0fb6241fa4 --- /dev/null +++ b/mc/beacon.go @@ -0,0 +1,91 @@ +package mc + +import ( + "log" + "net" +) + +type recv struct { + data []byte + src net.Addr +} + +type Beacon struct { + group string + port int + conns []*net.UDPConn + inbox chan []byte + outbox chan recv +} + +func NewBeacon(group string, port int) *Beacon { + b := &Beacon{ + group: group, + port: port, + inbox: make(chan []byte), + outbox: make(chan recv), + } + go b.run() + return b +} + +func (b *Beacon) Send(data []byte) { + b.inbox <- data +} + +func (b *Beacon) Recv() ([]byte, net.Addr) { + recv := <-b.outbox + return recv.data, recv.src +} + +func (b *Beacon) run() { + group := &net.UDPAddr{IP: net.ParseIP(b.group), Port: b.port} + + intfs, err := net.Interfaces() + if err != nil { + log.Fatal(err) + } + + for _, intf := range intfs { + intf := intf + + if debug { + dlog.Printf("trying interface %q", intf.Name) + } + conn, err := net.ListenMulticastUDP("udp4", &intf, group) + if err != nil { + if debug { + dlog.Printf("listen for multicast group on %q: %v", intf.Name, err) + } + } else { + b.conns = append(b.conns, conn) + } + } + + for _, conn := range b.conns { + conn := conn + go func() { + for { + var bs = make([]byte, 1500) + n, addr, err := conn.ReadFrom(bs) + if err != nil { + dlog.Println(err) + return + } + b.outbox <- recv{bs[:n], addr} + } + }() + } + + go func() { + for bs := range b.inbox { + for _, conn := range b.conns { + _, err := conn.WriteTo(bs, group) + if err != nil { + dlog.Println(err) + return + } + } + } + }() +} |