p2p/protocol/identity: smarter tracking observed addrs
- time them out (already was doing that with addrbook) - keep count to counter symmetric nats
Juan Batiz-Benet committed
Feb 5, 2015 at 10:15 UTC
ee4a9a27113169209a13288fd5ad1b010ee11204
4 files changed
+173
-4
p2p/peer/addr_manager.go
+1
-1
@@ -22,7 +22,7 @@ const (
22
RecentlyConnectedAddrTTL = time.Minute * 10
23
24
// OwnObservedAddrTTL is used for our own external addresses observed by peers.
25
- OwnObservedAddrTTL = time.Minute * 20
25
+ OwnObservedAddrTTL = time.Minute * 10
26
27
// PermanentAddrTTL is the ttl for a "permanent address" (e.g. bootstrap nodes)
28
// if we haven't shipped you an update to ipfs in 356 days
p2p/protocol/identify/id.go
+3
-3
@@ -47,7 +47,7 @@ type IDService struct {
47
48
// our own observed addresses.
49
// TODO: instead of expiring, remove these when we disconnect
50
- addrs peer.AddrManager
50
+ observedAddrs ObservedAddrSet
51
}
52
53
func NewIDService(h host.Host) *IDService {
@@ -61,7 +61,7 @@ func NewIDService(h host.Host) *IDService {
61
62
// OwnObservedAddrs returns the addresses peers have reported we've dialed from
63
func (ids *IDService) OwnObservedAddrs() []ma.Multiaddr {
64
- return ids.addrs.Addrs(ids.Host.ID())
64
+ return ids.observedAddrs.Addrs()
65
}
66
67
func (ids *IDService) IdentifyConn(c inet.Conn) {
@@ -250,7 +250,7 @@ func (ids *IDService) consumeObservedAddress(observed []byte, c inet.Conn) {
250
251
// ok! we have the observed version of one of our ListenAddresses!
252
log.Debugf("added own observed listen addr: %s --> %s", c.LocalMultiaddr(), maddr)
253
- ids.addrs.AddAddr(ids.Host.ID(), maddr, peer.OwnObservedAddrTTL)
253
+ ids.observedAddrs.Add(maddr)
254
}
255
256
func addrInAddrs(a ma.Multiaddr, as []ma.Multiaddr) bool {
p2p/protocol/identify/obsaddr.go
new
+96
@@ -0,0 +1,96 @@
1
+package identify
2
+
3
+import (
4
+ "sync"
5
+ "time"
6
+
7
+ peer "github.com/jbenet/go-ipfs/p2p/peer"
8
+
9
+ ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
10
+)
11
+
12
+// ObservedAddr is an entry for an address reported by our peers.
13
+// We only use addresses that:
14
+// - have been observed more than once. (counter symmetric nats)
15
+// - have been observed recently (10min), because our position in the
16
+// network, or network port mapppings, may have changed.
17
+type ObservedAddr struct {
18
+ Addr ma.Multiaddr
19
+ LastSeen time.Time
20
+ TimesSeen int
21
+}
22
+
23
+// ObservedAddrSet keeps track of a set of ObservedAddrs
24
+// the zero-value is ready to be used.
25
+type ObservedAddrSet struct {
26
+ sync.Mutex // guards whole datastruct.
27
+
28
+ addrs map[string]ObservedAddr
29
+ ttl time.Duration
30
+}
31
+
32
+func (oas *ObservedAddrSet) Addrs() []ma.Multiaddr {
33
+ oas.Lock()
34
+ defer oas.Unlock()
35
+
36
+ // for zero-value.
37
+ if oas.addrs == nil {
38
+ return nil
39
+ }
40
+
41
+ now := time.Now()
42
+ addrs := make([]ma.Multiaddr, 0, len(oas.addrs))
43
+ for s, a := range oas.addrs {
44
+ // remove timed out addresses.
45
+ if now.Sub(a.LastSeen) > oas.ttl {
46
+ delete(oas.addrs, s)
47
+ continue
48
+ }
49
+
50
+ // we only use an address if we've seen it more than once
51
+ // because symmetric nats may cause all our peers to see
52
+ // different port numbers and thus report always different
53
+ // addresses (different ports) for us. These wouldn't be
54
+ // very useful. We make the assumption that if we've
55
+ // connected to two different peers, and they both have
56
+ // reported seeing the same address, it is probably useful.
57
+ if a.TimesSeen > 1 {
58
+ addrs = append(addrs, a.Addr)
59
+ }
60
+ }
61
+ return addrs
62
+}
63
+
64
+func (oas *ObservedAddrSet) Add(addr ma.Multiaddr) {
65
+ oas.Lock()
66
+ defer oas.Unlock()
67
+
68
+ // for zero-value.
69
+ if oas.addrs == nil {
70
+ oas.addrs = make(map[string]ObservedAddr)
71
+ oas.ttl = peer.OwnObservedAddrTTL
72
+ }
73
+
74
+ s := addr.String()
75
+ oas.addrs[s] = ObservedAddr{
76
+ Addr: addr,
77
+ TimesSeen: oas.addrs[s].TimesSeen + 1,
78
+ LastSeen: time.Now(),
79
+ }
80
+}
81
+
82
+func (oas *ObservedAddrSet) SetTTL(ttl time.Duration) {
83
+ oas.Lock()
84
+ defer oas.Unlock()
85
+ oas.ttl = ttl
86
+}
87
+
88
+func (oas *ObservedAddrSet) TTL() time.Duration {
89
+ oas.Lock()
90
+ defer oas.Unlock()
91
+ // for zero-value.
92
+ if oas.addrs == nil {
93
+ oas.ttl = peer.OwnObservedAddrTTL
94
+ }
95
+ return oas.ttl
96
+}
p2p/protocol/identify/obsaddr_test.go
new
+73
@@ -0,0 +1,73 @@
1
+package identify
2
+
3
+import (
4
+ "testing"
5
+ "time"
6
+
7
+ ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8
+)
9
+
10
+// TestObsAddrSet
11
+func TestObsAddrSet(t *testing.T) {
12
+ m := func(s string) ma.Multiaddr {
13
+ m, err := ma.NewMultiaddr(s)
14
+ if err != nil {
15
+ t.Error(err)
16
+ }
17
+ return m
18
+ }
19
+
20
+ addrsMarch := func(a, b []ma.Multiaddr) bool {
21
+ for _, aa := range a {
22
+ found := false
23
+ for _, bb := range b {
24
+ if aa.Equal(bb) {
25
+ found = true
26
+ break
27
+ }
28
+ }
29
+ if !found {
30
+ return false
31
+ }
32
+ }
33
+ return true
34
+ }
35
+
36
+ a1 := m("/ip4/1.2.3.4/tcp/1231")
37
+ a2 := m("/ip4/1.2.3.4/tcp/1232")
38
+ a3 := m("/ip4/1.2.3.4/tcp/1233")
39
+
40
+ oas := ObservedAddrSet{}
41
+
42
+ if !addrsMarch(oas.Addrs(), nil) {
43
+ t.Error("addrs should be empty")
44
+ }
45
+
46
+ oas.Add(a1)
47
+ oas.Add(a2)
48
+ oas.Add(a3)
49
+
50
+ // these are all different so we should not yet get them.
51
+ if !addrsMarch(oas.Addrs(), nil) {
52
+ t.Error("addrs should _still_ be empty (once)")
53
+ }
54
+
55
+ oas.Add(a1)
56
+ if !addrsMarch(oas.Addrs(), []ma.Multiaddr{a1}) {
57
+ t.Error("addrs should only have a1")
58
+ }
59
+
60
+ oas.Add(a2)
61
+ oas.Add(a1)
62
+ oas.Add(a1)
63
+ if !addrsMarch(oas.Addrs(), []ma.Multiaddr{a1, a2}) {
64
+ t.Error("addrs should only have a1, a2")
65
+ }
66
+
67
+ // change the timeout constant so we can time it out.
68
+ oas.SetTTL(time.Millisecond * 200)
69
+ <-time.After(time.Millisecond * 210)
70
+ if !addrsMarch(oas.Addrs(), []ma.Multiaddr{nil}) {
71
+ t.Error("addrs should have timed out")
72
+ }
73
+}