beacon.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. if debug {
  41. dlog.Printf("trying %d interfaces", len(intfs))
  42. }
  43. for _, intf := range intfs {
  44. intf := intf
  45. if debug {
  46. dlog.Printf("trying interface %q", intf.Name)
  47. }
  48. conn, err := net.ListenMulticastUDP("udp4", &intf, group)
  49. if err != nil {
  50. if debug {
  51. dlog.Printf("failed to listen for multicast group on %q: %v", intf.Name, err)
  52. }
  53. } else {
  54. b.conns = append(b.conns, conn)
  55. if debug {
  56. dlog.Printf("listening for multicast group on %q", intf.Name)
  57. }
  58. }
  59. }
  60. for _, conn := range b.conns {
  61. conn := conn
  62. go func() {
  63. for {
  64. var bs = make([]byte, 1500)
  65. n, addr, err := conn.ReadFrom(bs)
  66. if err != nil {
  67. dlog.Println(err)
  68. return
  69. }
  70. if debug {
  71. dlog.Printf("recv %d bytes from %s on %v", n, addr, conn)
  72. }
  73. b.outbox <- recv{bs[:n], addr}
  74. }
  75. }()
  76. }
  77. go func() {
  78. for bs := range b.inbox {
  79. for _, conn := range b.conns {
  80. _, err := conn.WriteTo(bs, group)
  81. if err != nil {
  82. dlog.Println(err)
  83. return
  84. }
  85. if debug {
  86. dlog.Printf("sent %d bytes to %s on %v", len(bs), group, conn)
  87. }
  88. }
  89. }
  90. }()
  91. }