1
0
Fork 0
mirror of https://github.com/anyproto/anytype-heart.git synced 2025-06-09 09:35:00 +09:00

GO-3908 localdiscovery: sort ip addresses received from multicast according to sorted interfaces

This commit is contained in:
Roman Khafizianov 2024-08-12 21:52:51 +02:00
parent 3aa2832910
commit a579929231
No known key found for this signature in database
GPG key ID: F07A7D55A2684852
3 changed files with 98 additions and 9 deletions

View file

@ -20,9 +20,45 @@ type InterfaceAddr struct {
Prefix int
}
type InterfaceWithAddr struct {
net.Interface
cachedAddrs []net.Addr // ipv4 addresses
cachedErr error
}
type InterfacesAddrs struct {
Interfaces []net.Interface
Addrs []net.Addr
Interfaces []InterfaceWithAddr
Addrs []net.Addr // addrs without attachment to specific interface. Used as a fallback mechanism
}
func WrapInterfaces(ifaces []net.Interface) []InterfaceWithAddr {
var m = make([]InterfaceWithAddr, 0, len(ifaces))
for i := range ifaces {
m = append(m, InterfaceWithAddr{
Interface: ifaces[i],
})
}
return m
}
// GetAddr returns ipv4 only addresses for interface or cached one if set
func (i InterfaceWithAddr) GetAddr() []net.Addr {
if i.cachedAddrs != nil {
return i.cachedAddrs
}
if i.cachedErr != nil {
return nil
}
i.cachedAddrs, i.cachedErr = i.Addrs()
// filter-out ipv6
i.cachedAddrs = slice.Filter(i.cachedAddrs, func(addr net.Addr) bool {
if ip, ok := addr.(*net.IPNet); ok {
if ip.IP.To4() == nil {
return false
}
}
return true
})
return i.cachedAddrs
}
func (i InterfacesAddrs) Equal(other InterfacesAddrs) bool {
@ -71,7 +107,7 @@ func parseInterfaceName(name string) (prefix string, bus int, num int64) {
}
func (i InterfacesAddrs) SortWithPriority(priority []string) {
less := func(a, b net.Interface) bool {
less := func(a, b InterfaceWithAddr) bool {
aPrefix, aBus, aNum := parseInterfaceName(a.Name)
bPrefix, bBus, bNum := parseInterfaceName(b.Name)
@ -100,7 +136,7 @@ func (i InterfacesAddrs) SortWithPriority(priority []string) {
return false
}
}
slices.SortFunc(i.Interfaces, func(a, b net.Interface) int {
slices.SortFunc(i.Interfaces, func(a, b InterfaceWithAddr) int {
if less(a, b) {
return -1
}
@ -108,6 +144,14 @@ func (i InterfacesAddrs) SortWithPriority(priority []string) {
})
}
func (i InterfacesAddrs) NetInterfaces() []net.Interface {
var s = make([]net.Interface, 0, len(i.Interfaces))
for _, iface := range i.Interfaces {
s = append(s, iface.Interface)
}
return s
}
func getStrings(i InterfacesAddrs) (allStrings []string) {
for _, i := range i.Interfaces {
allStrings = append(allStrings, i.Name)
@ -118,3 +162,47 @@ func getStrings(i InterfacesAddrs) (allStrings []string) {
slices.Sort(allStrings)
return
}
func (i InterfacesAddrs) GetInterfaceByAddr(addr net.Addr) (net.Interface, bool) {
for _, iface := range i.Interfaces {
for _, addrInIface := range iface.GetAddr() {
if addr.String() == addrInIface.String() {
return iface.Interface, true
}
}
}
return net.Interface{}, false
}
func (i InterfacesAddrs) SortIPsLikeInterfaces(ips []net.IP) {
slices.SortFunc(ips, func(a, b net.IP) int {
pa, _ := i.findInterfacePosByIP(a)
pb, _ := i.findInterfacePosByIP(b)
if pa == -1 && pb != -1 {
return 1
}
if pa != -1 && pb == -1 {
return -1
}
if pa < pb {
return -1
} else if pa > pb {
return 1
}
return 0
})
}
func (i InterfacesAddrs) findInterfacePosByIP(ip net.IP) (pos int, equal bool) {
for position, iface := range i.Interfaces {
for _, addr := range iface.GetAddr() {
if ni, ok := addr.(*net.IPNet); ok {
if ni.Contains(ip) {
return position, ni.IP.Equal(ip)
}
}
}
}
return -1, false
}

View file

@ -32,9 +32,9 @@ func GetInterfacesAddrs() (iAddrs InterfacesAddrs, err error) {
if err != nil {
return
}
iAddrs.Interfaces = ifaces
iAddrs.Interfaces = WrapInterfaces(ifaces)
iAddrs.Interfaces = slice.Filter(iAddrs.Interfaces, func(iface net.Interface) bool {
iAddrs.Interfaces = slice.Filter(iAddrs.Interfaces, func(iface InterfaceWithAddr) bool {
return iface.Flags&net.FlagUp != 0 && iface.Flags&net.FlagMulticast != 0
})
return