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 ...@@ -3,6 +3,7 @@ package peer
import ( import (
"errors" "errors"
"sync" "sync"
"time"
ic "github.com/jbenet/go-ipfs/p2p/crypto" ic "github.com/jbenet/go-ipfs/p2p/crypto"
...@@ -11,6 +12,11 @@ import ( ...@@ -11,6 +12,11 @@ import (
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" 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 // Peerstore provides a threadsafe store of Peer related
// information. // information.
type Peerstore interface { type Peerstore interface {
...@@ -44,15 +50,28 @@ type AddressBook interface { ...@@ -44,15 +50,28 @@ type AddressBook interface {
SetAddresses(ID, []ma.Multiaddr) // Sets given addrs for ID (clears previously stored) 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 { type addressbook struct {
addrs map[ID]addressMap addrs map[ID]addressMap
ttl time.Duration // initial ttl
sync.RWMutex sync.RWMutex
} }
func newAddressbook() *addressbook { func newAddressbook() *addressbook {
return &addressbook{addrs: map[ID]addressMap{}} return &addressbook{
addrs: map[ID]addressMap{},
ttl: AddressTTL,
}
} }
func (ab *addressbook) Peers() []ID { func (ab *addressbook) Peers() []ID {
...@@ -74,11 +93,21 @@ func (ab *addressbook) Addresses(p ID) []ma.Multiaddr { ...@@ -74,11 +93,21 @@ func (ab *addressbook) Addresses(p ID) []ma.Multiaddr {
return nil return nil
} }
maddrs2 := make([]ma.Multiaddr, 0, len(maddrs)) good := make([]ma.Multiaddr, 0, len(maddrs))
for _, m := range maddrs { var expired []string
maddrs2 = append(maddrs2, m) 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) { func (ab *addressbook) AddAddress(p ID, m ma.Multiaddr) {
...@@ -94,8 +123,14 @@ func (ab *addressbook) AddAddresses(p ID, ms []ma.Multiaddr) { ...@@ -94,8 +123,14 @@ func (ab *addressbook) AddAddresses(p ID, ms []ma.Multiaddr) {
amap = addressMap{} amap = addressMap{}
ab.addrs[p] = amap ab.addrs[p] = amap
} }
ttl := time.Now().Add(ab.ttl)
for _, m := range ms { 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) { ...@@ -104,8 +139,9 @@ func (ab *addressbook) SetAddresses(p ID, ms []ma.Multiaddr) {
defer ab.Unlock() defer ab.Unlock()
amap := addressMap{} amap := addressMap{}
ttl := time.Now().Add(ab.ttl)
for _, m := range ms { 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 ab.addrs[p] = amap // clear what was there before
} }
......
...@@ -2,6 +2,7 @@ package peer ...@@ -2,6 +2,7 @@ package peer
import ( import (
"testing" "testing"
"time"
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
) )
...@@ -96,3 +97,89 @@ func TestAddresses(t *testing.T) { ...@@ -96,3 +97,89 @@ func TestAddresses(t *testing.T) {
test([]ma.Multiaddr{ma41, ma42, ma43, ma44}, ps.PeerInfo(id4).Addrs) test([]ma.Multiaddr{ma41, ma42, ma43, ma44}, ps.PeerInfo(id4).Addrs)
test([]ma.Multiaddr{ma51, ma52, ma53, ma54, ma55}, ps.PeerInfo(id5).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