Use undirected broadcast and WriteTo (fixes #75)

This commit is contained in:
Jakob Borg 2014-03-03 15:28:10 +01:00
parent 5d8f0f835e
commit ba59e0d3f0

View File

@ -80,24 +80,75 @@ func (d *Discoverer) sendAnnouncements() {
var errCounter = 0 var errCounter = 0
var err error var err error
for errCounter < maxErrors { remote := &net.UDPAddr{
for _, ipStr := range allBroadcasts() { IP: net.IP{255, 255, 255, 255},
var addrStr = ipStr + ":21025" Port: AnnouncementPort,
}
remote, err := net.ResolveUDPAddr("udp4", addrStr) for errCounter < maxErrors {
intfs, err := net.Interfaces()
if err != nil { if err != nil {
log.Printf("discover/external: %v; no external announcements", err) log.Printf("discover/listInterfaces: %v; no local announcements", err)
return return
} }
if Debug { for _, intf := range intfs {
log.Println("send announcement -> ", remote) if intf.Flags&(net.FlagBroadcast|net.FlagLoopback) == net.FlagBroadcast {
} addrs, err := intf.Addrs()
_, _, err = d.conn.WriteMsgUDP(buf, nil, remote)
if err != nil { if err != nil {
log.Println("discover/write: warning:", err) log.Println("discover/listAddrs: warning:", err)
errCounter++ errCounter++
} else { continue
}
var srcAddr string
for _, addr := range addrs {
if strings.Contains(addr.String(), ".") {
// Found an IPv4 adress
parts := strings.Split(addr.String(), "/")
srcAddr = parts[0]
break
}
}
if len(srcAddr) == 0 {
if Debug {
log.Println("discover: debug: no source address found on interface", intf.Name)
}
continue
}
iaddr, err := net.ResolveUDPAddr("udp4", srcAddr+":0")
if err != nil {
log.Println("discover/resolve: warning:", err)
errCounter++
continue
}
conn, err := net.ListenUDP("udp4", iaddr)
if err != nil {
log.Println("discover/listen: warning:", err)
errCounter++
continue
}
if Debug {
log.Println("discover: debug: send announcement from", conn.LocalAddr(), "to", remote, "on", intf.Name)
}
_, err = conn.WriteTo(buf, remote)
if err != nil {
// Some interfaces don't seem to support broadcast even though the flags claims they do, i.e. vmnet
conn.Close()
if Debug {
log.Println("discover/write: debug:", err)
}
errCounter++
continue
}
conn.Close()
errCounter = 0 errCounter = 0
} }
} }
@ -125,7 +176,7 @@ func (d *Discoverer) sendExtAnnouncements() {
if Debug { if Debug {
log.Println("send announcement -> ", remote) log.Println("send announcement -> ", remote)
} }
_, _, err = d.conn.WriteMsgUDP(buf, nil, remote) _, err = d.conn.WriteTo(buf, remote)
if err != nil { if err != nil {
log.Println("discover/write: warning:", err) log.Println("discover/write: warning:", err)
errCounter++ errCounter++
@ -289,38 +340,3 @@ func ipStr(ip []byte) string {
} }
return strings.Join(ss, s) return strings.Join(ss, s)
} }
func allBroadcasts() []string {
var bcasts = make(map[string]bool)
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil
}
for _, addr := range addrs {
switch {
case strings.HasPrefix(addr.String(), "127."):
// Ignore v4 localhost
case strings.Contains(addr.String(), ":"):
// Ignore all v6, because we need link local multicast there which I haven't implemented
default:
if in, ok := addr.(*net.IPNet); ok {
il := len(in.IP) - 1
ml := len(in.Mask) - 1
for i := range in.Mask {
in.IP[il-i] = in.IP[il-i] | ^in.Mask[ml-i]
}
parts := strings.Split(in.String(), "/")
bcasts[parts[0]] = true
}
}
}
var l []string
for ip := range bcasts {
l = append(l, ip)
}
return l
}