summaryrefslogtreecommitdiffstats
path: root/mc/beacon.go
diff options
context:
space:
mode:
Diffstat (limited to 'mc/beacon.go')
-rw-r--r--mc/beacon.go91
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
+ }
+ }
+ }
+ }()
+}