beacon.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. package mc
  2. import (
  3. "log"
  4. "net"
  5. )
  6. type recv struct {
  7. data []byte
  8. src net.Addr
  9. }
  10. type Beacon struct {
  11. group string
  12. port int
  13. conns []*net.UDPConn
  14. inbox chan []byte
  15. outbox chan recv
  16. }
  17. func NewBeacon(group string, port int) *Beacon {
  18. b := &Beacon{
  19. group: group,
  20. port: port,
  21. inbox: make(chan []byte),
  22. outbox: make(chan recv),
  23. }
  24. go b.run()
  25. return b
  26. }
  27. func (b *Beacon) Send(data []byte) {
  28. b.inbox <- data
  29. }
  30. func (b *Beacon) Recv() ([]byte, net.Addr) {
  31. recv := <-b.outbox
  32. return recv.data, recv.src
  33. }
  34. func (b *Beacon) run() {
  35. group := &net.UDPAddr{IP: net.ParseIP(b.group), Port: b.port}
  36. intfs, err := net.Interfaces()
  37. if err != nil {
  38. log.Fatal(err)
  39. }
  40. for _, intf := range intfs {
  41. intf := intf
  42. if debug {
  43. dlog.Printf("trying interface %q", intf.Name)
  44. }
  45. conn, err := net.ListenMulticastUDP("udp4", &intf, group)
  46. if err != nil {
  47. if debug {
  48. dlog.Printf("listen for multicast group on %q: %v", intf.Name, err)
  49. }
  50. } else {
  51. b.conns = append(b.conns, conn)
  52. }
  53. }
  54. for _, conn := range b.conns {
  55. conn := conn
  56. go func() {
  57. for {
  58. var bs = make([]byte, 1500)
  59. n, addr, err := conn.ReadFrom(bs)
  60. if err != nil {
  61. dlog.Println(err)
  62. return
  63. }
  64. b.outbox <- recv{bs[:n], addr}
  65. }
  66. }()
  67. }
  68. go func() {
  69. for bs := range b.inbox {
  70. for _, conn := range b.conns {
  71. _, err := conn.WriteTo(bs, group)
  72. if err != nil {
  73. dlog.Println(err)
  74. return
  75. }
  76. }
  77. }
  78. }()
  79. }