broadcast.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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 https://mozilla.org/MPL/2.0/.
  6. package beacon
  7. import (
  8. "net"
  9. "time"
  10. )
  11. func NewBroadcast(port int) Interface {
  12. c := newCast("broadcastBeacon")
  13. c.addReader(func(stop chan struct{}) error {
  14. return readBroadcasts(c.outbox, port, stop)
  15. })
  16. c.addWriter(func(stop chan struct{}) error {
  17. return writeBroadcasts(c.inbox, port, stop)
  18. })
  19. return c
  20. }
  21. func writeBroadcasts(inbox <-chan []byte, port int, stop chan struct{}) error {
  22. conn, err := net.ListenUDP("udp4", nil)
  23. if err != nil {
  24. l.Debugln(err)
  25. return err
  26. }
  27. done := make(chan struct{})
  28. defer close(done)
  29. go func() {
  30. select {
  31. case <-stop:
  32. case <-done:
  33. }
  34. conn.Close()
  35. }()
  36. for {
  37. var bs []byte
  38. select {
  39. case bs = <-inbox:
  40. case <-stop:
  41. return nil
  42. }
  43. addrs, err := net.InterfaceAddrs()
  44. if err != nil {
  45. l.Debugln(err)
  46. return err
  47. }
  48. var dsts []net.IP
  49. for _, addr := range addrs {
  50. if iaddr, ok := addr.(*net.IPNet); ok && len(iaddr.IP) >= 4 && iaddr.IP.IsGlobalUnicast() && iaddr.IP.To4() != nil {
  51. baddr := bcast(iaddr)
  52. dsts = append(dsts, baddr.IP)
  53. }
  54. }
  55. if len(dsts) == 0 {
  56. // Fall back to the general IPv4 broadcast address
  57. dsts = append(dsts, net.IP{0xff, 0xff, 0xff, 0xff})
  58. }
  59. l.Debugln("addresses:", dsts)
  60. success := 0
  61. for _, ip := range dsts {
  62. dst := &net.UDPAddr{IP: ip, Port: port}
  63. conn.SetWriteDeadline(time.Now().Add(time.Second))
  64. _, err = conn.WriteTo(bs, dst)
  65. conn.SetWriteDeadline(time.Time{})
  66. if nerr, ok := err.(net.Error); ok && nerr.Timeout() {
  67. // Write timeouts should not happen. We treat it as a fatal
  68. // error on the socket.
  69. l.Debugln(err)
  70. return err
  71. }
  72. if err != nil {
  73. // Some other error that we don't expect. Debug and continue.
  74. l.Debugln(err)
  75. continue
  76. }
  77. l.Debugf("sent %d bytes to %s", len(bs), dst)
  78. success++
  79. }
  80. if success == 0 {
  81. l.Debugln("couldn't send any braodcasts")
  82. return err
  83. }
  84. }
  85. }
  86. func readBroadcasts(outbox chan<- recv, port int, stop chan struct{}) error {
  87. conn, err := net.ListenUDP("udp4", &net.UDPAddr{Port: port})
  88. if err != nil {
  89. l.Debugln(err)
  90. return err
  91. }
  92. done := make(chan struct{})
  93. defer close(done)
  94. go func() {
  95. select {
  96. case <-stop:
  97. case <-done:
  98. }
  99. conn.Close()
  100. }()
  101. bs := make([]byte, 65536)
  102. for {
  103. n, addr, err := conn.ReadFrom(bs)
  104. if err != nil {
  105. l.Debugln(err)
  106. return err
  107. }
  108. l.Debugf("recv %d bytes from %s", n, addr)
  109. c := make([]byte, n)
  110. copy(c, bs)
  111. select {
  112. case outbox <- recv{c, addr}:
  113. case <-stop:
  114. return nil
  115. default:
  116. l.Debugln("dropping message")
  117. }
  118. }
  119. }
  120. func bcast(ip *net.IPNet) *net.IPNet {
  121. var bc = &net.IPNet{}
  122. bc.IP = make([]byte, len(ip.IP))
  123. copy(bc.IP, ip.IP)
  124. bc.Mask = ip.Mask
  125. offset := len(bc.IP) - len(bc.Mask)
  126. for i := range bc.IP {
  127. if i-offset >= 0 {
  128. bc.IP[i] = ip.IP[i] | ^ip.Mask[i-offset]
  129. }
  130. }
  131. return bc
  132. }