Files
weave-scope/app/resolver.go
2015-05-19 10:02:02 +00:00

87 lines
1.6 KiB
Go

package main
import (
"log"
"net"
"time"
)
// Resolver periodically tries to resolve the IP addresses for a given
// set of hostnames.
type Resolver struct {
quit chan struct{}
add func(string)
peers []peer
}
type peer struct {
hostname string
port string
}
// NewResolver starts a new resolver that periodically
// tries to resolve peers and the calls add() with all the
// resolved IPs. It explictiy supports hostnames which
// resolve to multiple IPs; it will repeatedly call
// add with the same IP, expecting the target to dedupe.
func NewResolver(peers []string, add func(string)) Resolver {
resolver := Resolver{
quit: make(chan struct{}),
add: add,
peers: prepareNames(peers),
}
go resolver.loop()
return resolver
}
func prepareNames(peers []string) []peer {
var results []peer
for _, p := range peers {
hostname, port, err := net.SplitHostPort(p)
if err != nil {
log.Printf("invalid address %s: %v", p, err)
continue
}
results = append(results, peer{hostname, port})
}
return results
}
func (r Resolver) loop() {
r.resolveHosts()
for {
tick := time.Tick(1 * time.Minute)
select {
case <-tick:
r.resolveHosts()
case <-r.quit:
return
}
}
}
func (r Resolver) resolveHosts() {
for _, peer := range r.peers {
addrs, err := net.LookupIP(peer.hostname)
if err != nil {
log.Printf("lookup %s: %v", peer.hostname, err)
continue
}
for _, addr := range addrs {
// For now, ignore IPv6
if addr.To4() == nil {
continue
}
r.add(net.JoinHostPort(addr.String(), peer.port))
}
}
}
// Stop this resolver.
func (r Resolver) Stop() {
r.quit <- struct{}{}
}