From 96df62bd5bae73d0136c975bbe6230cdeb9f1dbc Mon Sep 17 00:00:00 2001 From: Can ZHANG Date: Wed, 26 Sep 2018 16:52:35 +0800 Subject: [PATCH] Changes on discussion - map internal -> []{external -> { observer -> [time, direction] } } - some cleaning --- p2p/protocol/identify/obsaddr.go | 95 ++++++++++++++++++++------------ 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/p2p/protocol/identify/obsaddr.go b/p2p/protocol/identify/obsaddr.go index b8aa84c..61ccc0b 100644 --- a/p2p/protocol/identify/obsaddr.go +++ b/p2p/protocol/identify/obsaddr.go @@ -11,25 +11,27 @@ import ( const ActivationThresh = 4 +type observation struct { + seenTime time.Time + connDirection net.Direction +} + // ObservedAddr is an entry for an address reported by our peers. // We only use addresses that: // - have been observed at least 4 times in last 1h. (counter symmetric nats) // - have been observed at least once recently (1h), because our position in the // network, or network port mapppings, may have changed. type ObservedAddr struct { - Addr ma.Multiaddr // observed address by peers - InternalAddr ma.Multiaddr // corresponding internal address - SeenBy map[string]time.Time - LastSeen time.Time - ConnDirection net.Direction - Activated bool + Addr ma.Multiaddr + SeenBy map[string]observation // peer(observer) address -> observation info + LastSeen time.Time } -func (oa *ObservedAddr) TryActivate(ttl time.Duration) bool { +func (oa *ObservedAddr) activated(ttl time.Duration) bool { // cleanup SeenBy set now := time.Now() - for k, t := range oa.SeenBy { - if now.Sub(t) > ttl*ActivationThresh { + for k, ob := range oa.SeenBy { + if now.Sub(ob.seenTime) > ttl*ActivationThresh { delete(oa.SeenBy, k) } } @@ -44,32 +46,37 @@ func (oa *ObservedAddr) TryActivate(ttl time.Duration) bool { type ObservedAddrSet struct { sync.Mutex // guards whole datastruct. - addrs map[string]*ObservedAddr + // local(internal) address -> list of observed(external) addresses + addrs map[string][]*ObservedAddr ttl time.Duration } -func (oas *ObservedAddrSet) Addrs() []ma.Multiaddr { +// Addrs return all activated observed addresses +func (oas *ObservedAddrSet) Addrs() (addrs []ma.Multiaddr) { oas.Lock() defer oas.Unlock() // for zero-value. - if oas.addrs == nil { + if len(oas.addrs) == 0 { return nil } now := time.Now() - addrs := make([]ma.Multiaddr, 0, len(oas.addrs)) - for s, a := range oas.addrs { - // remove timed out addresses. - if now.Sub(a.LastSeen) > oas.ttl { - delete(oas.addrs, s) - continue - } - - if a.Activated || a.TryActivate(oas.ttl) { - addrs = append(addrs, a.Addr) + filteredAddrMap := make(map[string][]*ObservedAddr) + for local, observedAddrs := range oas.addrs { + filteredAddrs := make([]*ObservedAddr, 0, len(observedAddrs)) + for _, a := range observedAddrs { + // leave only alive observed addresses + if now.Sub(a.LastSeen) <= oas.ttl { + filteredAddrs = append(filteredAddrs, a) + if a.activated(oas.ttl) { + addrs = append(addrs, a.Addr) + } + } } + filteredAddrMap[local] = filteredAddrs } + oas.addrs = filteredAddrMap return addrs } @@ -81,27 +88,43 @@ func (oas *ObservedAddrSet) Add(observed, local, observer ma.Multiaddr, // for zero-value. if oas.addrs == nil { - oas.addrs = make(map[string]*ObservedAddr) + oas.addrs = make(map[string][]*ObservedAddr) oas.ttl = pstore.OwnObservedAddrTTL } - s := observed.String() - oa, found := oas.addrs[s] + now := time.Now() + observerString := observerGroup(observer) + localString := local.String() + observedAddr := &ObservedAddr{ + Addr: observed, + SeenBy: map[string]observation{ + observerString: { + seenTime: now, + connDirection: direction, + }, + }, + LastSeen: now, + } - // first time seeing address. + observedAddrs, found := oas.addrs[localString] + // map key not exist yet, init with new values if !found { - oa = &ObservedAddr{ - Addr: observed, - InternalAddr: local, - SeenBy: make(map[string]time.Time), - ConnDirection: direction, + oas.addrs[localString] = []*ObservedAddr{observedAddr} + return + } + // check if observed address seen yet, if so, update it + for i, previousObserved := range observedAddrs { + if previousObserved.Addr.Equal(observed) { + observedAddrs[i].SeenBy[observerString] = observation{ + seenTime: now, + connDirection: direction, + } + observedAddrs[i].LastSeen = now + return } - oas.addrs[s] = oa } - - // mark the observer - oa.SeenBy[observerGroup(observer)] = time.Now() - oa.LastSeen = time.Now() + // observed address not seen yet, append it + oas.addrs[localString] = append(oas.addrs[localString], observedAddr) } // observerGroup is a function that determines what part of -- GitLab