mirror of
				https://github.com/coredns/coredns.git
				synced 2025-11-03 18:53:13 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			77 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package loadbalance
 | 
						|
 | 
						|
import (
 | 
						|
	"log"
 | 
						|
 | 
						|
	"github.com/miekg/dns"
 | 
						|
)
 | 
						|
 | 
						|
type RoundRobinResponseWriter struct {
 | 
						|
	dns.ResponseWriter
 | 
						|
}
 | 
						|
 | 
						|
func NewRoundRobinResponseWriter(w dns.ResponseWriter) *RoundRobinResponseWriter {
 | 
						|
	return &RoundRobinResponseWriter{w}
 | 
						|
}
 | 
						|
 | 
						|
func (r *RoundRobinResponseWriter) WriteMsg(res *dns.Msg) error {
 | 
						|
	if res.Rcode != dns.RcodeSuccess {
 | 
						|
		return r.ResponseWriter.WriteMsg(res)
 | 
						|
	}
 | 
						|
 | 
						|
	res.Answer = roundRobin(res.Answer)
 | 
						|
	res.Ns = roundRobin(res.Ns)
 | 
						|
	res.Extra = roundRobin(res.Extra)
 | 
						|
 | 
						|
	return r.ResponseWriter.WriteMsg(res)
 | 
						|
}
 | 
						|
 | 
						|
func roundRobin(in []dns.RR) []dns.RR {
 | 
						|
	cname := []dns.RR{}
 | 
						|
	address := []dns.RR{}
 | 
						|
	rest := []dns.RR{}
 | 
						|
	for _, r := range in {
 | 
						|
		switch r.Header().Rrtype {
 | 
						|
		case dns.TypeCNAME:
 | 
						|
			cname = append(cname, r)
 | 
						|
		case dns.TypeA, dns.TypeAAAA:
 | 
						|
			address = append(address, r)
 | 
						|
		default:
 | 
						|
			rest = append(rest, r)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	switch l := len(address); l {
 | 
						|
	case 0, 1:
 | 
						|
		break
 | 
						|
	case 2:
 | 
						|
		if dns.Id()%2 == 0 {
 | 
						|
			address[0], address[1] = address[1], address[0]
 | 
						|
		}
 | 
						|
	default:
 | 
						|
		for j := 0; j < l*(int(dns.Id())%4+1); j++ {
 | 
						|
			q := int(dns.Id()) % l
 | 
						|
			p := int(dns.Id()) % l
 | 
						|
			if q == p {
 | 
						|
				p = (p + 1) % l
 | 
						|
			}
 | 
						|
			address[q], address[p] = address[p], address[q]
 | 
						|
		}
 | 
						|
	}
 | 
						|
	out := append(cname, rest...)
 | 
						|
	out = append(out, address...)
 | 
						|
	return out
 | 
						|
}
 | 
						|
 | 
						|
// Should we pack and unpack here to fiddle with the packet... Not likely.
 | 
						|
func (r *RoundRobinResponseWriter) Write(buf []byte) (int, error) {
 | 
						|
	log.Printf("[WARNING] RoundRobin called with Write: no shuffling records")
 | 
						|
	n, err := r.ResponseWriter.Write(buf)
 | 
						|
	return n, err
 | 
						|
}
 | 
						|
 | 
						|
func (r *RoundRobinResponseWriter) Hijack() {
 | 
						|
	r.ResponseWriter.Hijack()
 | 
						|
	return
 | 
						|
}
 |