OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / github.com / miekg / dns / sanitize.go
1 package dns
2
3 // Dedup removes identical RRs from rrs. It preserves the original ordering.
4 // The lowest TTL of any duplicates is used in the remaining one. Dedup modifies
5 // rrs.
6 // m is used to store the RRs temporary. If it is nil a new map will be allocated.
7 func Dedup(rrs []RR, m map[string]RR) []RR {
8
9         if m == nil {
10                 m = make(map[string]RR)
11         }
12         // Save the keys, so we don't have to call normalizedString twice.
13         keys := make([]*string, 0, len(rrs))
14
15         for _, r := range rrs {
16                 key := normalizedString(r)
17                 keys = append(keys, &key)
18                 if mr, ok := m[key]; ok {
19                         // Shortest TTL wins.
20                         rh, mrh := r.Header(), mr.Header()
21                         if mrh.Ttl > rh.Ttl {
22                                 mrh.Ttl = rh.Ttl
23                         }
24                         continue
25                 }
26
27                 m[key] = r
28         }
29         // If the length of the result map equals the amount of RRs we got,
30         // it means they were all different. We can then just return the original rrset.
31         if len(m) == len(rrs) {
32                 return rrs
33         }
34
35         j := 0
36         for i, r := range rrs {
37                 // If keys[i] lives in the map, we should copy and remove it.
38                 if _, ok := m[*keys[i]]; ok {
39                         delete(m, *keys[i])
40                         rrs[j] = r
41                         j++
42                 }
43
44                 if len(m) == 0 {
45                         break
46                 }
47         }
48
49         return rrs[:j]
50 }
51
52 // normalizedString returns a normalized string from r. The TTL
53 // is removed and the domain name is lowercased. We go from this:
54 // DomainName<TAB>TTL<TAB>CLASS<TAB>TYPE<TAB>RDATA to:
55 // lowercasename<TAB>CLASS<TAB>TYPE...
56 func normalizedString(r RR) string {
57         // A string Go DNS makes has: domainname<TAB>TTL<TAB>...
58         b := []byte(r.String())
59
60         // find the first non-escaped tab, then another, so we capture where the TTL lives.
61         esc := false
62         ttlStart, ttlEnd := 0, 0
63         for i := 0; i < len(b) && ttlEnd == 0; i++ {
64                 switch {
65                 case b[i] == '\\':
66                         esc = !esc
67                 case b[i] == '\t' && !esc:
68                         if ttlStart == 0 {
69                                 ttlStart = i
70                                 continue
71                         }
72                         if ttlEnd == 0 {
73                                 ttlEnd = i
74                         }
75                 case b[i] >= 'A' && b[i] <= 'Z' && !esc:
76                         b[i] += 32
77                 default:
78                         esc = false
79                 }
80         }
81
82         // remove TTL.
83         copy(b[ttlStart:], b[ttlEnd:])
84         cut := ttlEnd - ttlStart
85         return string(b[:len(b)-cut])
86 }