| package sockaddr |
| |
| import "bytes" |
| |
| type IPAddrs []IPAddr |
| |
| func (s IPAddrs) Len() int { return len(s) } |
| func (s IPAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] } |
| |
| // // SortIPAddrsByCmp is a type that satisfies sort.Interface and can be used |
| // // by the routines in this package. The SortIPAddrsByCmp type is used to |
| // // sort IPAddrs by Cmp() |
| // type SortIPAddrsByCmp struct{ IPAddrs } |
| |
| // // Less reports whether the element with index i should sort before the |
| // // element with index j. |
| // func (s SortIPAddrsByCmp) Less(i, j int) bool { |
| // // Sort by Type, then address, then port number. |
| // return Less(s.IPAddrs[i], s.IPAddrs[j]) |
| // } |
| |
| // SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and |
| // can be used by the routines in this package. The |
| // SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest |
| // network (most specific to largest network). |
| type SortIPAddrsByNetworkSize struct{ IPAddrs } |
| |
| // Less reports whether the element with index i should sort before the |
| // element with index j. |
| func (s SortIPAddrsByNetworkSize) Less(i, j int) bool { |
| // Sort masks with a larger binary value (i.e. fewer hosts per network |
| // prefix) after masks with a smaller value (larger number of hosts per |
| // prefix). |
| switch bytes.Compare([]byte(*s.IPAddrs[i].NetIPMask()), []byte(*s.IPAddrs[j].NetIPMask())) { |
| case 0: |
| // Fall through to the second test if the net.IPMasks are the |
| // same. |
| break |
| case 1: |
| return true |
| case -1: |
| return false |
| default: |
| panic("bad, m'kay?") |
| } |
| |
| // Sort IPs based on the length (i.e. prefer IPv4 over IPv6). |
| iLen := len(*s.IPAddrs[i].NetIP()) |
| jLen := len(*s.IPAddrs[j].NetIP()) |
| if iLen != jLen { |
| return iLen > jLen |
| } |
| |
| // Sort IPs based on their network address from lowest to highest. |
| switch bytes.Compare(s.IPAddrs[i].NetIPNet().IP, s.IPAddrs[j].NetIPNet().IP) { |
| case 0: |
| break |
| case 1: |
| return false |
| case -1: |
| return true |
| default: |
| panic("lol wut?") |
| } |
| |
| // If a host does not have a port set, it always sorts after hosts |
| // that have a port (e.g. a host with a /32 and port number is more |
| // specific and should sort first over a host with a /32 but no port |
| // set). |
| if s.IPAddrs[i].IPPort() == 0 || s.IPAddrs[j].IPPort() == 0 { |
| return false |
| } |
| return s.IPAddrs[i].IPPort() < s.IPAddrs[j].IPPort() |
| } |
| |
| // SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and |
| // can be used by the routines in this package. The |
| // SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest |
| // network (most specific to largest network). |
| type SortIPAddrsBySpecificMaskLen struct{ IPAddrs } |
| |
| // Less reports whether the element with index i should sort before the |
| // element with index j. |
| func (s SortIPAddrsBySpecificMaskLen) Less(i, j int) bool { |
| return s.IPAddrs[i].Maskbits() > s.IPAddrs[j].Maskbits() |
| } |
| |
| // SortIPAddrsByBroadMaskLen is a type that satisfies sort.Interface and can |
| // be used by the routines in this package. The SortIPAddrsByBroadMaskLen |
| // type is used to sort IPAddrs by largest network (i.e. largest subnets |
| // first). |
| type SortIPAddrsByBroadMaskLen struct{ IPAddrs } |
| |
| // Less reports whether the element with index i should sort before the |
| // element with index j. |
| func (s SortIPAddrsByBroadMaskLen) Less(i, j int) bool { |
| return s.IPAddrs[i].Maskbits() < s.IPAddrs[j].Maskbits() |
| } |