87 lines
1.5 KiB
Go
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]])
|
|
})
|
|
}
|