1
0
mirror of https://github.com/golang/go synced 2024-11-25 06:57:58 -07:00

net: sort records returned by LookupSRV

R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/4518061
This commit is contained in:
Gary Burd 2011-05-16 17:48:00 -04:00 committed by Russ Cox
parent 8ef0d181f6
commit aea17570c0

View File

@ -398,10 +398,49 @@ type SRV struct {
Weight uint16
}
// byPriorityWeight sorts SRV records by ascending priority and weight.
type byPriorityWeight []*SRV
func (s byPriorityWeight) Len() int { return len(s) }
func (s byPriorityWeight) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byPriorityWeight) Less(i, j int) bool {
return s[i].Priority < s[j].Priority ||
(s[i].Priority == s[j].Priority && s[i].Weight < s[j].Weight)
}
// shuffleSRVByWeight shuffles SRV records by weight using the algorithm
// described in RFC 2782.
func shuffleSRVByWeight(addrs []*SRV) {
sum := 0
for _, addr := range addrs {
sum += int(addr.Weight)
}
for sum > 0 && len(addrs) > 1 {
s := 0
n := rand.Intn(sum + 1)
for i := range addrs {
s += int(addrs[i].Weight)
if s >= n {
if i > 0 {
t := addrs[i]
copy(addrs[1:i+1], addrs[0:i])
addrs[0] = t
}
break
}
}
sum -= int(addrs[0].Weight)
addrs = addrs[1:]
}
}
// LookupSRV tries to resolve an SRV query of the given service,
// protocol, and domain name, as specified in RFC 2782. In most cases
// the proto argument can be the same as the corresponding
// Addr.Network().
// Addr.Network(). The returned records are sorted by priority
// and randomized by weight within a priority.
func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.Error) {
target := "_" + service + "._" + proto + "." + name
var records []dnsRR
@ -414,6 +453,15 @@ func LookupSRV(service, proto, name string) (cname string, addrs []*SRV, err os.
r := rr.(*dnsRR_SRV)
addrs[i] = &SRV{r.Target, r.Port, r.Priority, r.Weight}
}
sort.Sort(byPriorityWeight(addrs))
i := 0
for j := 1; j < len(addrs); j++ {
if addrs[i].Priority != addrs[j].Priority {
shuffleSRVByWeight(addrs[i:j])
i = j
}
}
shuffleSRVByWeight(addrs[i:len(addrs)])
return
}