Commit 983822f3 authored by Juan Batiz-Benet's avatar Juan Batiz-Benet

p2p/peer: addresses expire after an hour

parent 3118777a
......@@ -3,6 +3,7 @@ package peer
import (
"errors"
"sync"
"time"
ic "github.com/jbenet/go-ipfs/p2p/crypto"
......@@ -11,6 +12,11 @@ import (
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
)
const (
// AddressTTL is the expiration time of addresses.
AddressTTL = time.Hour
)
// Peerstore provides a threadsafe store of Peer related
// information.
type Peerstore interface {
......@@ -44,15 +50,28 @@ type AddressBook interface {
SetAddresses(ID, []ma.Multiaddr) // Sets given addrs for ID (clears previously stored)
}
type addressMap map[string]ma.Multiaddr
type expiringAddr struct {
Addr ma.Multiaddr
TTL time.Time
}
func (e *expiringAddr) Expired() bool {
return time.Now().After(e.TTL)
}
type addressMap map[string]expiringAddr
type addressbook struct {
addrs map[ID]addressMap
ttl time.Duration // initial ttl
sync.RWMutex
}
func newAddressbook() *addressbook {
return &addressbook{addrs: map[ID]addressMap{}}
return &addressbook{
addrs: map[ID]addressMap{},
ttl: AddressTTL,
}
}
func (ab *addressbook) Peers() []ID {
......@@ -74,11 +93,21 @@ func (ab *addressbook) Addresses(p ID) []ma.Multiaddr {
return nil
}
maddrs2 := make([]ma.Multiaddr, 0, len(maddrs))
for _, m := range maddrs {
maddrs2 = append(maddrs2, m)
good := make([]ma.Multiaddr, 0, len(maddrs))
var expired []string
for s, m := range maddrs {
if m.Expired() {
expired = append(expired, s)
} else {
good = append(good, m.Addr)
}
}
// clean up the expired ones.
for _, s := range expired {
delete(ab.addrs[p], s)
}
return maddrs2
return good
}
func (ab *addressbook) AddAddress(p ID, m ma.Multiaddr) {
......@@ -94,8 +123,14 @@ func (ab *addressbook) AddAddresses(p ID, ms []ma.Multiaddr) {
amap = addressMap{}
ab.addrs[p] = amap
}
ttl := time.Now().Add(ab.ttl)
for _, m := range ms {
amap[m.String()] = m
// re-set all of them for new ttl.
amap[m.String()] = expiringAddr{
Addr: m,
TTL: ttl,
}
}
}
......@@ -104,8 +139,9 @@ func (ab *addressbook) SetAddresses(p ID, ms []ma.Multiaddr) {
defer ab.Unlock()
amap := addressMap{}
ttl := time.Now().Add(ab.ttl)
for _, m := range ms {
amap[m.String()] = m
amap[m.String()] = expiringAddr{Addr: m, TTL: ttl}
}
ab.addrs[p] = amap // clear what was there before
}
......
......@@ -2,6 +2,7 @@ package peer
import (
"testing"
"time"
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
)
......@@ -96,3 +97,89 @@ func TestAddresses(t *testing.T) {
test([]ma.Multiaddr{ma41, ma42, ma43, ma44}, ps.PeerInfo(id4).Addrs)
test([]ma.Multiaddr{ma51, ma52, ma53, ma54, ma55}, ps.PeerInfo(id5).Addrs)
}
func TestAddressTTL(t *testing.T) {
ps := NewPeerstore()
id1 := IDS(t, "QmcNstKuwBBoVTpSCSDrwzjgrRcaYXK833Psuz2EMHwyQN")
ma1 := MA(t, "/ip4/1.2.3.1/tcp/1111")
ma2 := MA(t, "/ip4/2.2.3.2/tcp/2222")
ma3 := MA(t, "/ip4/3.2.3.3/tcp/3333")
ma4 := MA(t, "/ip4/4.2.3.3/tcp/4444")
ma5 := MA(t, "/ip4/5.2.3.3/tcp/5555")
ps.AddAddress(id1, ma1)
ps.AddAddress(id1, ma2)
ps.AddAddress(id1, ma3)
ps.AddAddress(id1, ma4)
ps.AddAddress(id1, ma5)
test := func(exp, act []ma.Multiaddr) {
if len(exp) != len(act) {
t.Fatal("lengths not the same")
}
for _, a := range exp {
found := false
for _, b := range act {
if a.Equal(b) {
found = true
break
}
}
if !found {
t.Fatal("expected address %s not found", a)
}
}
}
testTTL := func(ttle time.Duration, id ID, addr ma.Multiaddr) {
ab := ps.(*peerstore).addressbook
ttlat := ab.addrs[id][addr.String()].TTL
ttla := ttlat.Sub(time.Now())
if ttla > ttle {
t.Error("ttl is greater than expected", ttle, ttla)
}
if ttla < (ttle / 2) {
t.Error("ttl is smaller than expected", ttle/2, ttla)
}
}
// should they are there
ab := ps.(*peerstore).addressbook
if len(ab.addrs[id1]) != 5 {
t.Error("incorrect addr count", len(ab.addrs[id1]), ab.addrs[id1])
}
// test the Addresses return value
test([]ma.Multiaddr{ma1, ma2, ma3, ma4, ma5}, ps.Addresses(id1))
test([]ma.Multiaddr{ma1, ma2, ma3, ma4, ma5}, ps.PeerInfo(id1).Addrs)
// check the addr TTL is a bit smaller than the init TTL
testTTL(AddressTTL, id1, ma1)
testTTL(AddressTTL, id1, ma2)
testTTL(AddressTTL, id1, ma3)
testTTL(AddressTTL, id1, ma4)
testTTL(AddressTTL, id1, ma5)
// change the TTL
setTTL := func(id ID, addr ma.Multiaddr, ttl time.Time) {
a := ab.addrs[id][addr.String()]
a.TTL = ttl
ab.addrs[id][addr.String()] = a
}
setTTL(id1, ma1, time.Now().Add(-1*time.Second))
setTTL(id1, ma2, time.Now().Add(-1*time.Hour))
setTTL(id1, ma3, time.Now().Add(-1*AddressTTL))
// should no longer list those
test([]ma.Multiaddr{ma4, ma5}, ps.Addresses(id1))
test([]ma.Multiaddr{ma4, ma5}, ps.PeerInfo(id1).Addrs)
// should no longer be there
if len(ab.addrs[id1]) != 2 {
t.Error("incorrect addr count", len(ab.addrs[id1]), ab.addrs[id1])
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment