multicast.go 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. package beacon
  7. import "net"
  8. type Multicast struct {
  9. conn *net.UDPConn
  10. addr *net.UDPAddr
  11. inbox chan []byte
  12. outbox chan recv
  13. }
  14. func NewMulticast(addr string) (*Multicast, error) {
  15. gaddr, err := net.ResolveUDPAddr("udp", addr)
  16. if err != nil {
  17. return nil, err
  18. }
  19. conn, err := net.ListenMulticastUDP("udp", nil, gaddr)
  20. if err != nil {
  21. return nil, err
  22. }
  23. b := &Multicast{
  24. conn: conn,
  25. addr: gaddr,
  26. inbox: make(chan []byte),
  27. outbox: make(chan recv, 16),
  28. }
  29. go genericReader(b.conn, b.outbox)
  30. go b.writer()
  31. return b, nil
  32. }
  33. func (b *Multicast) Send(data []byte) {
  34. b.inbox <- data
  35. }
  36. func (b *Multicast) Recv() ([]byte, net.Addr) {
  37. recv := <-b.outbox
  38. return recv.data, recv.src
  39. }
  40. func (b *Multicast) writer() {
  41. for bs := range b.inbox {
  42. intfs, err := net.Interfaces()
  43. if err != nil {
  44. if debug {
  45. l.Debugln("multicast interfaces:", err)
  46. }
  47. continue
  48. }
  49. for _, intf := range intfs {
  50. if intf.Flags&net.FlagUp != 0 && intf.Flags&net.FlagMulticast != 0 {
  51. addr := *b.addr
  52. addr.Zone = intf.Name
  53. _, err = b.conn.WriteTo(bs, &addr)
  54. if err != nil {
  55. if debug {
  56. l.Debugln(err, "on write to", addr)
  57. }
  58. } else if debug {
  59. l.Debugf("sent %d bytes to %s", len(bs), addr.String())
  60. }
  61. }
  62. }
  63. }
  64. }