initial commit
This commit is contained in:
commit
e6feefa1fc
26 files changed
+4476
No files matched your search
+108
@@ -0,0 +1,108 @@
|
||||
package weave
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type MacCacheEntry struct {
|
||||
lastSeen time.Time
|
||||
peer *Peer
|
||||
}
|
||||
|
||||
type MacCache struct {
|
||||
sync.RWMutex
|
||||
table map[uint64]*MacCacheEntry
|
||||
maxAge time.Duration
|
||||
expiryTimer *time.Timer
|
||||
}
|
||||
|
||||
func NewMacCache(maxAge time.Duration) *MacCache {
|
||||
res := &MacCache{
|
||||
table: make(map[uint64]*MacCacheEntry),
|
||||
maxAge: maxAge}
|
||||
res.setExpiryTimer()
|
||||
return res
|
||||
}
|
||||
|
||||
func (cache *MacCache) Enter(mac net.HardwareAddr, peer *Peer) bool {
|
||||
key := macint(mac)
|
||||
now := time.Now()
|
||||
cache.RLock()
|
||||
entry, found := cache.table[key]
|
||||
if found && entry.peer == peer && now.Before(entry.lastSeen.Add(cache.maxAge/10)) {
|
||||
cache.RUnlock()
|
||||
return false
|
||||
} else {
|
||||
cache.RUnlock()
|
||||
}
|
||||
cache.Lock()
|
||||
defer cache.Unlock()
|
||||
entry, found = cache.table[key]
|
||||
if !found {
|
||||
cache.table[key] = &MacCacheEntry{lastSeen: now, peer: peer}
|
||||
return true
|
||||
}
|
||||
if entry.peer != peer {
|
||||
entry.lastSeen = now
|
||||
entry.peer = peer
|
||||
return true
|
||||
}
|
||||
if now.After(entry.lastSeen.Add(cache.maxAge / 10)) {
|
||||
entry.lastSeen = now
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (cache *MacCache) Lookup(mac net.HardwareAddr) (*Peer, bool) {
|
||||
key := macint(mac)
|
||||
cache.RLock()
|
||||
defer cache.RUnlock()
|
||||
entry, found := cache.table[key]
|
||||
if !found {
|
||||
return nil, false
|
||||
}
|
||||
return entry.peer, true
|
||||
}
|
||||
|
||||
func (cache *MacCache) Delete(peer *Peer) bool {
|
||||
found := false
|
||||
cache.Lock()
|
||||
defer cache.Unlock()
|
||||
for key, entry := range cache.table {
|
||||
if entry.peer == peer {
|
||||
delete(cache.table, key)
|
||||
found = true
|
||||
}
|
||||
}
|
||||
return found
|
||||
}
|
||||
|
||||
func (cache *MacCache) String() string {
|
||||
var buf bytes.Buffer
|
||||
cache.RLock()
|
||||
defer cache.RUnlock()
|
||||
for key, entry := range cache.table {
|
||||
buf.WriteString(fmt.Sprintf("%v -> %s (%v)\n", intmac(key), entry.peer.Name, entry.lastSeen))
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (cache *MacCache) setExpiryTimer() {
|
||||
cache.expiryTimer = time.AfterFunc(cache.maxAge/10, func() { cache.expire() })
|
||||
}
|
||||
|
||||
func (cache *MacCache) expire() {
|
||||
now := time.Now()
|
||||
cache.Lock()
|
||||
defer cache.Unlock()
|
||||
for key, entry := range cache.table {
|
||||
if now.After(entry.lastSeen.Add(cache.maxAge)) {
|
||||
delete(cache.table, key)
|
||||
}
|
||||
}
|
||||
cache.setExpiryTimer()
|
||||
}
|
||||
Reference in new issue
Block a user