mirror of
https://github.com/anyproto/anytype-heart.git
synced 2025-06-10 01:51:07 +09:00
120 lines
2.7 KiB
Go
120 lines
2.7 KiB
Go
package addrs
|
|
|
|
import (
|
|
"net"
|
|
"regexp"
|
|
"strconv"
|
|
|
|
"golang.org/x/exp/slices"
|
|
|
|
"github.com/anyproto/anytype-heart/util/slice"
|
|
)
|
|
|
|
type Interface struct {
|
|
net.Interface
|
|
Addrs []InterfaceAddr
|
|
}
|
|
|
|
type InterfaceAddr struct {
|
|
Ip []byte
|
|
Prefix int
|
|
}
|
|
|
|
type InterfacesAddrs struct {
|
|
Interfaces []net.Interface
|
|
Addrs []net.Addr
|
|
}
|
|
|
|
func (i InterfacesAddrs) Equal(other InterfacesAddrs) bool {
|
|
if len(other.Interfaces) != len(i.Interfaces) {
|
|
return false
|
|
}
|
|
if len(other.Addrs) != len(i.Addrs) {
|
|
return false
|
|
}
|
|
myStr := getStrings(i)
|
|
otherStr := getStrings(other)
|
|
return slices.Equal(myStr, otherStr)
|
|
}
|
|
|
|
var (
|
|
ifaceRe = regexp.MustCompile(`^([a-z]*?)([0-9]+)$`)
|
|
// ifaceReBusSlot used for prefixBusSlot naming schema used in newer linux distros https://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-net_id.c#n20
|
|
ifaceReBusSlot = regexp.MustCompile(`^([a-z]*?)p([0-9]+)s([0-9a-f]+)$`)
|
|
)
|
|
|
|
func parseInterfaceName(name string) (prefix string, bus int, num int64) {
|
|
// try new-style naming schema first (enp0s3, wlp2s0, ...)
|
|
res := ifaceReBusSlot.FindStringSubmatch(name)
|
|
if len(res) > 0 {
|
|
if len(res) > 1 {
|
|
prefix = res[1]
|
|
}
|
|
if len(res) > 2 {
|
|
bus, _ = strconv.Atoi(res[2])
|
|
}
|
|
if len(res) > 3 {
|
|
numHex := res[3]
|
|
num, _ = strconv.ParseInt(numHex, 16, 32)
|
|
}
|
|
return
|
|
}
|
|
// try old-style naming schema (eth0, wlan0, ...)
|
|
res = ifaceRe.FindStringSubmatch(name)
|
|
if len(res) > 1 {
|
|
prefix = res[1]
|
|
}
|
|
if len(res) > 2 {
|
|
num, _ = strconv.ParseInt(res[2], 10, 32)
|
|
}
|
|
return
|
|
}
|
|
|
|
func (i InterfacesAddrs) SortWithPriority(priority []string) {
|
|
less := func(a, b net.Interface) bool {
|
|
aPrefix, aBus, aNum := parseInterfaceName(a.Name)
|
|
bPrefix, bBus, bNum := parseInterfaceName(b.Name)
|
|
|
|
aPrioirity := slice.FindPos(priority, aPrefix)
|
|
bPrioirity := slice.FindPos(priority, bPrefix)
|
|
|
|
if aPrefix == bPrefix {
|
|
return aNum < bNum
|
|
} else if aPrioirity == -1 && bPrioirity == -1 {
|
|
// sort alphabetically
|
|
return aPrefix < bPrefix
|
|
} else if aPrioirity != -1 && bPrioirity != -1 {
|
|
// in case we have [eth, wlan]
|
|
if aPrioirity == bPrioirity {
|
|
// prioritize eth0 over wlan0
|
|
return aPrioirity < bPrioirity
|
|
}
|
|
// prioritise wlan1 over eth8
|
|
if aBus != bBus {
|
|
return aBus < bBus
|
|
}
|
|
return aNum < bNum
|
|
} else if aPrioirity != -1 {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
slices.SortFunc(i.Interfaces, func(a, b net.Interface) int {
|
|
if less(a, b) {
|
|
return -1
|
|
}
|
|
return 1
|
|
})
|
|
}
|
|
|
|
func getStrings(i InterfacesAddrs) (allStrings []string) {
|
|
for _, i := range i.Interfaces {
|
|
allStrings = append(allStrings, i.Name)
|
|
}
|
|
for _, i := range i.Addrs {
|
|
allStrings = append(allStrings, i.String())
|
|
}
|
|
slices.Sort(allStrings)
|
|
return
|
|
}
|