@cryptotaxi247 / kubo / commits / 56d900fa1

p2p/peer: addressbook can now clear addrs

Juan Batiz-Benet committed Jan 26, 2015 at 12:06 UTC 56d900fa1058a357599236b5434ec83d2019b923
4 files changed +194 -19
p2p/peer/addr/addrsrcs.go new
+70
@@ -0,0 +1,70 @@
1 +// Package addr provides utility functions to handle peer addresses.
2 +package addr
3 +
4 +import (
5 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
6 +)
7 +
8 +// AddrSource is a source of addresses. It allows clients to retrieve
9 +// a set of addresses at a last possible moment in time. It is used
10 +// to query a set of addresses that may change over time, as a result
11 +// of the network changing interfaces or mappings.
12 +type Source interface {
13 + Addrs() []ma.Multiaddr
14 +}
15 +
16 +// CombineSources returns a new AddrSource which is the
17 +// concatenation of all input AddrSources:
18 +//
19 +// combined := CombinedSources(a, b)
20 +// combined.Addrs() // append(a.Addrs(), b.Addrs()...)
21 +//
22 +func CombineSources(srcs ...Source) Source {
23 + return combinedAS(srcs)
24 +}
25 +
26 +type combinedAS []Source
27 +
28 +func (cas combinedAS) Addrs() []ma.Multiaddr {
29 + var addrs []ma.Multiaddr
30 + for _, s := range cas {
31 + addrs = append(addrs, s.Addrs()...)
32 + }
33 + return addrs
34 +}
35 +
36 +// UniqueSource returns a new AddrSource which omits duplicate
37 +// addresses from the inputs:
38 +//
39 +// unique := UniqueSource(a, b)
40 +// unique.Addrs() // append(a.Addrs(), b.Addrs()...)
41 +// // but only adds each addr once.
42 +//
43 +func UniqueSource(srcs ...Source) Source {
44 + return uniqueAS(srcs)
45 +}
46 +
47 +type uniqueAS []Source
48 +
49 +func (uas uniqueAS) Addrs() []ma.Multiaddr {
50 + seen := make(map[string]struct{})
51 + var addrs []ma.Multiaddr
52 + for _, s := range uas {
53 + for _, a := range s.Addrs() {
54 + s := a.String()
55 + if _, found := seen[s]; !found {
56 + addrs = append(addrs, a)
57 + seen[s] = struct{}{}
58 + }
59 + }
60 + }
61 + return addrs
62 +}
63 +
64 +// Slice is a simple slice of addresses that implements
65 +// the AddrSource interface.
66 +type Slice []ma.Multiaddr
67 +
68 +func (as Slice) Addrs() []ma.Multiaddr {
69 + return as
70 +}
p2p/peer/addr/addrsrcs_test.go new
+78
@@ -0,0 +1,78 @@
1 +package addr
2 +
3 +import (
4 + "fmt"
5 + "testing"
6 +
7 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8 +)
9 +
10 +func newAddrOrFatal(t *testing.T, s string) ma.Multiaddr {
11 + a, err := ma.NewMultiaddr(s)
12 + if err != nil {
13 + t.Fatal("error parsing multiaddr", err)
14 + }
15 + return a
16 +}
17 +
18 +func newAddrs(t *testing.T, n int) []ma.Multiaddr {
19 + addrs := make([]ma.Multiaddr, n)
20 + for i := 0; i < n; i++ {
21 + s := fmt.Sprintf("/ip4/1.2.3.4/tcp/%d", i)
22 + addrs[i] = newAddrOrFatal(t, s)
23 + }
24 + return addrs
25 +}
26 +
27 +func addrSetsSame(a, b []ma.Multiaddr) bool {
28 + if len(a) != len(b) {
29 + return false
30 + }
31 + for i, aa := range a {
32 + bb := b[i]
33 + if !aa.Equal(bb) {
34 + return false
35 + }
36 + }
37 + return true
38 +}
39 +
40 +func addrSourcesSame(a, b Source) bool {
41 + return addrSetsSame(a.Addrs(), b.Addrs())
42 +}
43 +
44 +func TestAddrCombine(t *testing.T) {
45 + addrs := newAddrs(t, 30)
46 + a := Slice(addrs[0:10])
47 + b := Slice(addrs[10:20])
48 + c := Slice(addrs[20:30])
49 + d := CombineSources(a, b, c)
50 + if !addrSetsSame(addrs, d.Addrs()) {
51 + t.Error("addrs differ")
52 + }
53 + if !addrSourcesSame(Slice(addrs), d) {
54 + t.Error("addrs differ")
55 + }
56 +}
57 +
58 +func TestAddrUnique(t *testing.T) {
59 +
60 + addrs := newAddrs(t, 40)
61 + a := Slice(addrs[0:20])
62 + b := Slice(addrs[10:30])
63 + c := Slice(addrs[20:40])
64 + d := CombineSources(a, b, c)
65 + e := UniqueSource(a, b, c)
66 + if addrSetsSame(addrs, d.Addrs()) {
67 + t.Error("addrs same")
68 + }
69 + if addrSourcesSame(Slice(addrs), d) {
70 + t.Error("addrs same")
71 + }
72 + if !addrSetsSame(addrs, e.Addrs()) {
73 + t.Error("addrs differ", addrs, "\n\n", e.Addrs(), "\n\n")
74 + }
75 + if !addrSourcesSame(Slice(addrs), e) {
76 + t.Error("addrs differ", addrs, "\n\n", e.Addrs(), "\n\n")
77 + }
78 +}
p2p/peer/peerstore.go
+18 -12
@@ -38,9 +38,10 @@ type Peerstore interface {
38
39 // AddressBook tracks the addresses of Peers
40 type AddressBook interface {
41 - Addresses(ID) []ma.Multiaddr
42 - AddAddress(ID, ma.Multiaddr)
43 - AddAddresses(ID, []ma.Multiaddr)
41 + Addresses(ID) []ma.Multiaddr // returns addresses for ID
42 + AddAddress(ID, ma.Multiaddr) // Adds given addr for ID
43 + AddAddresses(ID, []ma.Multiaddr) // Adds given addrs for ID
44 + SetAddresses(ID, []ma.Multiaddr) // Sets given addrs for ID (clears previously stored)
45 }
46
47 type addressMap map[string]ma.Multiaddr
@@ -81,27 +82,32 @@ func (ab *addressbook) Addresses(p ID) []ma.Multiaddr {
82 }
83
84 func (ab *addressbook) AddAddress(p ID, m ma.Multiaddr) {
85 + ab.AddAddresses(p, []ma.Multiaddr{m})
86 +}
87 +
88 +func (ab *addressbook) AddAddresses(p ID, ms []ma.Multiaddr) {
89 ab.Lock()
90 defer ab.Unlock()
91
87 - _, found := ab.addrs[p]
92 + amap, found := ab.addrs[p]
93 if !found {
89 - ab.addrs[p] = addressMap{}
94 + amap = addressMap{}
95 + ab.addrs[p] = amap
96 + }
97 + for _, m := range ms {
98 + amap[m.String()] = m
99 }
91 - ab.addrs[p][m.String()] = m
100 }
101
94 -func (ab *addressbook) AddAddresses(p ID, ms []ma.Multiaddr) {
102 +func (ab *addressbook) SetAddresses(p ID, ms []ma.Multiaddr) {
103 ab.Lock()
104 defer ab.Unlock()
105
106 + amap := addressMap{}
107 for _, m := range ms {
99 - _, found := ab.addrs[p]
100 - if !found {
101 - ab.addrs[p] = addressMap{}
102 - }
103 - ab.addrs[p][m.String()] = m
108 + amap[m.String()] = m
109 }
110 + ab.addrs[p] = amap // clear what was there before
111 }
112
113 // KeyBook tracks the Public keys of Peers.
p2p/peer/peerstore_test.go
+28 -7
@@ -29,20 +29,37 @@ func TestAddresses(t *testing.T) {
29 id1 := IDS(t, "QmcNstKuwBBoVTpSCSDrwzjgrRcaYXK833Psuz2EMHwyQN")
30 id2 := IDS(t, "QmRmPL3FDZKE3Qiwv1RosLdwdvbvg17b2hB39QPScgWKKZ")
31 id3 := IDS(t, "QmPhi7vBsChP7sjRoZGgg7bcKqF6MmCcQwvRbDte8aJ6Kn")
32 + id4 := IDS(t, "QmPhi7vBsChP7sjRoZGgg7bcKqF6MmCcQwvRbDte8aJ5Kn")
33 + id5 := IDS(t, "QmPhi7vBsChP7sjRoZGgg7bcKqF6MmCcQwvRbDte8aJ5Km")
34
35 ma11 := MA(t, "/ip4/1.2.3.1/tcp/1111")
34 - ma21 := MA(t, "/ip4/1.2.3.2/tcp/1111")
35 - ma22 := MA(t, "/ip4/1.2.3.2/tcp/2222")
36 - ma31 := MA(t, "/ip4/1.2.3.3/tcp/1111")
37 - ma32 := MA(t, "/ip4/1.2.3.3/tcp/2222")
38 - ma33 := MA(t, "/ip4/1.2.3.3/tcp/3333")
36 + ma21 := MA(t, "/ip4/2.2.3.2/tcp/1111")
37 + ma22 := MA(t, "/ip4/2.2.3.2/tcp/2222")
38 + ma31 := MA(t, "/ip4/3.2.3.3/tcp/1111")
39 + ma32 := MA(t, "/ip4/3.2.3.3/tcp/2222")
40 + ma33 := MA(t, "/ip4/3.2.3.3/tcp/3333")
41 + ma41 := MA(t, "/ip4/4.2.3.3/tcp/1111")
42 + ma42 := MA(t, "/ip4/4.2.3.3/tcp/2222")
43 + ma43 := MA(t, "/ip4/4.2.3.3/tcp/3333")
44 + ma44 := MA(t, "/ip4/4.2.3.3/tcp/4444")
45 + ma51 := MA(t, "/ip4/5.2.3.3/tcp/1111")
46 + ma52 := MA(t, "/ip4/5.2.3.3/tcp/2222")
47 + ma53 := MA(t, "/ip4/5.2.3.3/tcp/3333")
48 + ma54 := MA(t, "/ip4/5.2.3.3/tcp/4444")
49 + ma55 := MA(t, "/ip4/5.2.3.3/tcp/5555")
50
51 ps.AddAddress(id1, ma11)
41 - ps.AddAddress(id2, ma21)
42 - ps.AddAddress(id2, ma22)
52 + ps.AddAddresses(id2, []ma.Multiaddr{ma21, ma22})
53 + ps.AddAddresses(id2, []ma.Multiaddr{ma21, ma22}) // idempotency
54 ps.AddAddress(id3, ma31)
55 ps.AddAddress(id3, ma32)
56 ps.AddAddress(id3, ma33)
57 + ps.AddAddress(id3, ma33) // idempotency
58 + ps.AddAddress(id3, ma33)
59 + ps.AddAddresses(id4, []ma.Multiaddr{ma41, ma42, ma43, ma44}) // multiple
60 + ps.AddAddresses(id5, []ma.Multiaddr{ma21, ma22}) // clearing
61 + ps.AddAddresses(id5, []ma.Multiaddr{ma41, ma42, ma43, ma44}) // clearing
62 + ps.SetAddresses(id5, []ma.Multiaddr{ma51, ma52, ma53, ma54, ma55}) // clearing
63
64 test := func(exp, act []ma.Multiaddr) {
65 if len(exp) != len(act) {
@@ -69,9 +86,13 @@ func TestAddresses(t *testing.T) {
86 test([]ma.Multiaddr{ma11}, ps.Addresses(id1))
87 test([]ma.Multiaddr{ma21, ma22}, ps.Addresses(id2))
88 test([]ma.Multiaddr{ma31, ma32, ma33}, ps.Addresses(id3))
89 + test([]ma.Multiaddr{ma41, ma42, ma43, ma44}, ps.Addresses(id4))
90 + test([]ma.Multiaddr{ma51, ma52, ma53, ma54, ma55}, ps.Addresses(id5))
91
92 // test also the PeerInfo return
93 test([]ma.Multiaddr{ma11}, ps.PeerInfo(id1).Addrs)
94 test([]ma.Multiaddr{ma21, ma22}, ps.PeerInfo(id2).Addrs)
95 test([]ma.Multiaddr{ma31, ma32, ma33}, ps.PeerInfo(id3).Addrs)
96 + test([]ma.Multiaddr{ma41, ma42, ma43, ma44}, ps.PeerInfo(id4).Addrs)
97 + test([]ma.Multiaddr{ma51, ma52, ma53, ma54, ma55}, ps.PeerInfo(id5).Addrs)
98 }