123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- package sockaddr
- import (
- "bytes"
- "sort"
- )
- // SockAddrs is a slice of SockAddrs
- type SockAddrs []SockAddr
- func (s SockAddrs) Len() int { return len(s) }
- func (s SockAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
- // CmpAddrFunc is the function signature that must be met to be used in the
- // OrderedAddrBy multiAddrSorter
- type CmpAddrFunc func(p1, p2 *SockAddr) int
- // multiAddrSorter implements the Sort interface, sorting the SockAddrs within.
- type multiAddrSorter struct {
- addrs SockAddrs
- cmp []CmpAddrFunc
- }
- // Sort sorts the argument slice according to the Cmp functions passed to
- // OrderedAddrBy.
- func (ms *multiAddrSorter) Sort(sockAddrs SockAddrs) {
- ms.addrs = sockAddrs
- sort.Sort(ms)
- }
- // OrderedAddrBy sorts SockAddr by the list of sort function pointers.
- func OrderedAddrBy(cmpFuncs ...CmpAddrFunc) *multiAddrSorter {
- return &multiAddrSorter{
- cmp: cmpFuncs,
- }
- }
- // Len is part of sort.Interface.
- func (ms *multiAddrSorter) Len() int {
- return len(ms.addrs)
- }
- // Less is part of sort.Interface. It is implemented by looping along the
- // Cmp() functions until it finds a comparison that is either less than,
- // equal to, or greater than.
- func (ms *multiAddrSorter) Less(i, j int) bool {
- p, q := &ms.addrs[i], &ms.addrs[j]
- // Try all but the last comparison.
- var k int
- for k = 0; k < len(ms.cmp)-1; k++ {
- cmp := ms.cmp[k]
- x := cmp(p, q)
- switch x {
- case -1:
- // p < q, so we have a decision.
- return true
- case 1:
- // p > q, so we have a decision.
- return false
- }
- // p == q; try the next comparison.
- }
- // All comparisons to here said "equal", so just return whatever the
- // final comparison reports.
- switch ms.cmp[k](p, q) {
- case -1:
- return true
- case 1:
- return false
- default:
- // Still a tie! Now what?
- return false
- }
- }
- // Swap is part of sort.Interface.
- func (ms *multiAddrSorter) Swap(i, j int) {
- ms.addrs[i], ms.addrs[j] = ms.addrs[j], ms.addrs[i]
- }
- const (
- // NOTE (sean@): These constants are here for code readability only and
- // are sprucing up the code for readability purposes. Some of the
- // Cmp*() variants have confusing logic (especially when dealing with
- // mixed-type comparisons) and this, I think, has made it easier to grok
- // the code faster.
- sortReceiverBeforeArg = -1
- sortDeferDecision = 0
- sortArgBeforeReceiver = 1
- )
- // AscAddress is a sorting function to sort SockAddrs by their respective
- // address type. Non-equal types are deferred in the sort.
- func AscAddress(p1Ptr, p2Ptr *SockAddr) int {
- p1 := *p1Ptr
- p2 := *p2Ptr
- switch v := p1.(type) {
- case IPv4Addr:
- return v.CmpAddress(p2)
- case IPv6Addr:
- return v.CmpAddress(p2)
- case UnixSock:
- return v.CmpAddress(p2)
- default:
- return sortDeferDecision
- }
- }
- // AscPort is a sorting function to sort SockAddrs by their respective address
- // type. Non-equal types are deferred in the sort.
- func AscPort(p1Ptr, p2Ptr *SockAddr) int {
- p1 := *p1Ptr
- p2 := *p2Ptr
- switch v := p1.(type) {
- case IPv4Addr:
- return v.CmpPort(p2)
- case IPv6Addr:
- return v.CmpPort(p2)
- default:
- return sortDeferDecision
- }
- }
- // AscPrivate is a sorting function to sort "more secure" private values before
- // "more public" values. Both IPv4 and IPv6 are compared against RFC6890
- // (RFC6890 includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and
- // IPv6 includes RFC4193).
- func AscPrivate(p1Ptr, p2Ptr *SockAddr) int {
- p1 := *p1Ptr
- p2 := *p2Ptr
- switch v := p1.(type) {
- case IPv4Addr, IPv6Addr:
- return v.CmpRFC(6890, p2)
- default:
- return sortDeferDecision
- }
- }
- // AscNetworkSize is a sorting function to sort SockAddrs based on their network
- // size. Non-equal types are deferred in the sort.
- func AscNetworkSize(p1Ptr, p2Ptr *SockAddr) int {
- p1 := *p1Ptr
- p2 := *p2Ptr
- p1Type := p1.Type()
- p2Type := p2.Type()
- // Network size operations on non-IP types make no sense
- if p1Type != p2Type && p1Type != TypeIP {
- return sortDeferDecision
- }
- ipA := p1.(IPAddr)
- ipB := p2.(IPAddr)
- return bytes.Compare([]byte(*ipA.NetIPMask()), []byte(*ipB.NetIPMask()))
- }
- // AscType is a sorting function to sort "more secure" types before
- // "less-secure" types.
- func AscType(p1Ptr, p2Ptr *SockAddr) int {
- p1 := *p1Ptr
- p2 := *p2Ptr
- p1Type := p1.Type()
- p2Type := p2.Type()
- switch {
- case p1Type < p2Type:
- return sortReceiverBeforeArg
- case p1Type == p2Type:
- return sortDeferDecision
- case p1Type > p2Type:
- return sortArgBeforeReceiver
- default:
- return sortDeferDecision
- }
- }
- // FilterByType returns two lists: a list of matched and unmatched SockAddrs
- func (sas SockAddrs) FilterByType(type_ SockAddrType) (matched, excluded SockAddrs) {
- matched = make(SockAddrs, 0, len(sas))
- excluded = make(SockAddrs, 0, len(sas))
- for _, sa := range sas {
- if sa.Type()&type_ != 0 {
- matched = append(matched, sa)
- } else {
- excluded = append(excluded, sa)
- }
- }
- return matched, excluded
- }
|