2015-02-05 18:15:16 +00:00
|
|
|
package identify
|
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
2015-03-31 03:04:32 +00:00
|
|
|
peer "github.com/ipfs/go-ipfs/p2p/peer"
|
2015-02-05 18:15:16 +00:00
|
|
|
|
2015-03-31 03:04:32 +00:00
|
|
|
ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
|
2015-02-05 18:15:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// ObservedAddr is an entry for an address reported by our peers.
|
|
|
|
// We only use addresses that:
|
|
|
|
// - have been observed more than once. (counter symmetric nats)
|
|
|
|
// - have been observed recently (10min), because our position in the
|
|
|
|
// network, or network port mapppings, may have changed.
|
|
|
|
type ObservedAddr struct {
|
|
|
|
Addr ma.Multiaddr
|
|
|
|
LastSeen time.Time
|
|
|
|
TimesSeen int
|
|
|
|
}
|
|
|
|
|
|
|
|
// ObservedAddrSet keeps track of a set of ObservedAddrs
|
|
|
|
// the zero-value is ready to be used.
|
|
|
|
type ObservedAddrSet struct {
|
|
|
|
sync.Mutex // guards whole datastruct.
|
|
|
|
|
|
|
|
addrs map[string]ObservedAddr
|
|
|
|
ttl time.Duration
|
|
|
|
}
|
|
|
|
|
|
|
|
func (oas *ObservedAddrSet) Addrs() []ma.Multiaddr {
|
|
|
|
oas.Lock()
|
|
|
|
defer oas.Unlock()
|
|
|
|
|
|
|
|
// for zero-value.
|
|
|
|
if oas.addrs == nil {
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
// we only use an address if we've seen it more than once
|
|
|
|
// because symmetric nats may cause all our peers to see
|
|
|
|
// different port numbers and thus report always different
|
|
|
|
// addresses (different ports) for us. These wouldn't be
|
|
|
|
// very useful. We make the assumption that if we've
|
|
|
|
// connected to two different peers, and they both have
|
|
|
|
// reported seeing the same address, it is probably useful.
|
|
|
|
if a.TimesSeen > 1 {
|
|
|
|
addrs = append(addrs, a.Addr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return addrs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (oas *ObservedAddrSet) Add(addr ma.Multiaddr) {
|
|
|
|
oas.Lock()
|
|
|
|
defer oas.Unlock()
|
|
|
|
|
|
|
|
// for zero-value.
|
|
|
|
if oas.addrs == nil {
|
|
|
|
oas.addrs = make(map[string]ObservedAddr)
|
|
|
|
oas.ttl = peer.OwnObservedAddrTTL
|
|
|
|
}
|
|
|
|
|
|
|
|
s := addr.String()
|
|
|
|
oas.addrs[s] = ObservedAddr{
|
|
|
|
Addr: addr,
|
|
|
|
TimesSeen: oas.addrs[s].TimesSeen + 1,
|
|
|
|
LastSeen: time.Now(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (oas *ObservedAddrSet) SetTTL(ttl time.Duration) {
|
|
|
|
oas.Lock()
|
|
|
|
defer oas.Unlock()
|
|
|
|
oas.ttl = ttl
|
|
|
|
}
|
|
|
|
|
|
|
|
func (oas *ObservedAddrSet) TTL() time.Duration {
|
|
|
|
oas.Lock()
|
|
|
|
defer oas.Unlock()
|
|
|
|
// for zero-value.
|
|
|
|
if oas.addrs == nil {
|
|
|
|
oas.ttl = peer.OwnObservedAddrTTL
|
|
|
|
}
|
|
|
|
return oas.ttl
|
|
|
|
}
|