vppn/peer/pubaddrs.go
J. David Lee 1d3cc1f959 refactor-for-testability (#3)
Co-authored-by: jdl <jdl@desktop>
Co-authored-by: jdl <jdl@crumpington.com>
Reviewed-on: #3
2025-03-01 20:02:27 +00:00

87 lines
1.5 KiB
Go

package peer
import (
"net/netip"
"sort"
"sync"
"time"
)
type pubAddrStore struct {
lock sync.Mutex
localPub bool
localAddr netip.AddrPort
lastSeen map[netip.AddrPort]time.Time
addrList []netip.AddrPort
}
func newPubAddrStore(localAddr netip.AddrPort) *pubAddrStore {
return &pubAddrStore{
localPub: localAddr.IsValid(),
localAddr: localAddr,
lastSeen: map[netip.AddrPort]time.Time{},
addrList: make([]netip.AddrPort, 0, 32),
}
}
func (store *pubAddrStore) Store(addr netip.AddrPort) {
if store.localPub {
return
}
if !addr.IsValid() {
return
}
if addr.Addr().IsPrivate() {
return
}
store.lock.Lock()
defer store.lock.Unlock()
if _, exists := store.lastSeen[addr]; !exists {
store.addrList = append(store.addrList, addr)
}
store.lastSeen[addr] = time.Now()
store.sort()
}
func (store *pubAddrStore) Get() (addrs [8]netip.AddrPort) {
store.lock.Lock()
defer store.lock.Unlock()
store.clean()
if store.localPub {
addrs[0] = store.localAddr
return
}
copy(addrs[:], store.addrList)
return
}
func (store *pubAddrStore) clean() {
if store.localPub {
return
}
for ip, lastSeen := range store.lastSeen {
if time.Since(lastSeen) > timeoutInterval {
delete(store.lastSeen, ip)
}
}
store.addrList = store.addrList[:0]
for ip := range store.lastSeen {
store.addrList = append(store.addrList, ip)
}
store.sort()
}
func (store *pubAddrStore) sort() {
sort.Slice(store.addrList, func(i, j int) bool {
return store.lastSeen[store.addrList[j]].Before(store.lastSeen[store.addrList[i]])
})
}