swarm addr checks
Juan Batiz-Benet committed
Jan 9, 2015 at 06:03 UTC
06299297c5d6dec152dbb6162158ab12ab264ee3
4 files changed
+177
p2p/net/swarm/addr.go
+69
@@ -9,6 +9,75 @@ import (
9
manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
10
)
11
12
+// SupportedTransportStrings is the list of supported transports for the swarm.
13
+// These are strings of encapsulated multiaddr protocols. E.g.:
14
+// /ip4/tcp
15
+var SupportedTransportStrings = []string{
16
+ "/ip4/tcp",
17
+ "/ip6/tcp",
18
+ // "/ip4/udp/utp", disabled because the lib is broken
19
+ // "/ip6/udp/utp", disabled because the lib is broken
20
+ // "/ip4/udp/udt", disabled because the lib doesnt work on arm
21
+ // "/ip6/udp/udt", disabled because the lib doesnt work on arm
22
+}
23
+
24
+// SupportedTransportProtocols is the list of supported transports for the swarm.
25
+// These are []ma.Protocol lists. Populated at runtime from SupportedTransportStrings
26
+var SupportedTransportProtocols = [][]ma.Protocol{}
27
+
28
+func init() {
29
+ // initialize SupportedTransportProtocols
30
+ transports := make([][]ma.Protocol, len(SupportedTransportStrings))
31
+ for _, s := range SupportedTransportStrings {
32
+ t, err := ma.ProtocolsWithString(s)
33
+ if err != nil {
34
+ panic(err) // important to fix this in the codebase
35
+ }
36
+ transports = append(transports, t)
37
+ }
38
+ SupportedTransportProtocols = transports
39
+}
40
+
41
+// FilterAddrs is a filter that removes certain addresses
42
+// from a list. the addresses removed are those known NOT
43
+// to work with swarm. Namely, addresses with UTP.
44
+func FilterAddrs(a []ma.Multiaddr) []ma.Multiaddr {
45
+ b := make([]ma.Multiaddr, 0, len(a))
46
+ for _, addr := range a {
47
+ if AddrUsable(addr) {
48
+ b = append(b, addr)
49
+ }
50
+ }
51
+ return b
52
+}
53
+
54
+// AddrUsable returns whether the swarm can use this addr.
55
+func AddrUsable(a ma.Multiaddr) bool {
56
+ // test the address protocol list is in SupportedTransportProtocols
57
+
58
+ matches := func(a, b []ma.Protocol) bool {
59
+ if len(a) != len(b) {
60
+ return false
61
+ }
62
+
63
+ for i := range a {
64
+ if a[i].Code != b[i].Code {
65
+ return false
66
+ }
67
+ }
68
+ return true
69
+ }
70
+
71
+ transport := a.Protocols()
72
+ for _, supported := range SupportedTransportProtocols {
73
+ if matches(supported, transport) {
74
+ return true
75
+ }
76
+ }
77
+
78
+ return false
79
+}
80
+
81
// ListenAddresses returns a list of addresses at which this swarm listens.
82
func (s *Swarm) ListenAddresses() []ma.Multiaddr {
83
listeners := s.swarm.Listeners()
p2p/net/swarm/addr_test.go
new
+97
@@ -0,0 +1,97 @@
1
+package swarm
2
+
3
+import (
4
+ "testing"
5
+
6
+ peer "github.com/jbenet/go-ipfs/p2p/peer"
7
+ testutil "github.com/jbenet/go-ipfs/util/testutil"
8
+
9
+ context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
10
+ ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
11
+)
12
+
13
+func TestFilterAddrs(t *testing.T) {
14
+
15
+ m := func(s string) ma.Multiaddr {
16
+ maddr, err := ma.NewMultiaddr(s)
17
+ if err != nil {
18
+ t.Fatal(err)
19
+ }
20
+ return maddr
21
+ }
22
+
23
+ bad := []ma.Multiaddr{
24
+ m("/ip4/1.2.3.4/udp/1234"), // unreliable
25
+ m("/ip4/1.2.3.4/udp/1234/sctp/1234"), // not in manet
26
+ m("/ip4/1.2.3.4/udp/1234/utp"), // utp is broken
27
+ m("/ip4/1.2.3.4/udp/1234/udt"), // udt is broken on arm
28
+ }
29
+
30
+ good := []ma.Multiaddr{
31
+ m("/ip4/127.0.0.1/tcp/1234"),
32
+ m("/ip6/::1/tcp/1234"),
33
+ }
34
+
35
+ goodAndBad := append(good, bad...)
36
+
37
+ // test filters
38
+
39
+ for _, a := range bad {
40
+ if AddrUsable(a) {
41
+ t.Errorf("addr %s should be unusable", a)
42
+ }
43
+ }
44
+
45
+ for _, a := range good {
46
+ if !AddrUsable(a) {
47
+ t.Errorf("addr %s should be usable", a)
48
+ }
49
+ }
50
+
51
+ subtestAddrsEqual(t, FilterAddrs(bad), []ma.Multiaddr{})
52
+ subtestAddrsEqual(t, FilterAddrs(good), good)
53
+ subtestAddrsEqual(t, FilterAddrs(goodAndBad), good)
54
+
55
+ // now test it with swarm
56
+
57
+ id, err := testutil.RandPeerID()
58
+ if err != nil {
59
+ t.Fatal(err)
60
+ }
61
+
62
+ ps := peer.NewPeerstore()
63
+ ctx := context.Background()
64
+
65
+ if _, err := NewNetwork(ctx, bad, id, ps); err == nil {
66
+ t.Fatal("should have failed to create swarm")
67
+ }
68
+
69
+ if _, err := NewNetwork(ctx, good, id, ps); err != nil {
70
+ t.Fatal("should have succeeded in creating swarm", err)
71
+ }
72
+
73
+ if _, err := NewNetwork(ctx, goodAndBad, id, ps); err == nil {
74
+ t.Fatal("should have failed to create swarm")
75
+ }
76
+}
77
+
78
+func subtestAddrsEqual(t *testing.T, a, b []ma.Multiaddr) {
79
+ if len(a) != len(b) {
80
+ t.Error(t)
81
+ }
82
+
83
+ in := func(addr ma.Multiaddr, l []ma.Multiaddr) bool {
84
+ for _, addr2 := range l {
85
+ if addr.Equal(addr2) {
86
+ return true
87
+ }
88
+ }
89
+ return false
90
+ }
91
+
92
+ for _, aa := range a {
93
+ if !in(aa, b) {
94
+ t.Errorf("%s not in %s", aa, b)
95
+ }
96
+ }
97
+}
p2p/net/swarm/swarm_listen.go
+9
@@ -1,6 +1,8 @@
1
package swarm
2
3
import (
4
+ "fmt"
5
+
6
conn "github.com/jbenet/go-ipfs/p2p/net/conn"
7
lgbl "github.com/jbenet/go-ipfs/util/eventlog/loggables"
8
@@ -12,6 +14,13 @@ import (
14
15
// Open listeners for each network the swarm should listen on
16
func (s *Swarm) listen(addrs []ma.Multiaddr) error {
17
+
18
+ for _, addr := range addrs {
19
+ if !AddrUsable(addr) {
20
+ return fmt.Errorf("cannot use addr: %s", addr)
21
+ }
22
+ }
23
+
24
retErr := multierr.New()
25
26
// listen on every address
p2p/test/util/util.go
+2
@@ -36,3 +36,5 @@ func GenHostSwarm(t *testing.T, ctx context.Context) *bhost.BasicHost {
36
n := GenSwarmNetwork(t, ctx)
37
return bhost.New(n)
38
}
39
+
40
+var RandPeerID = tu.RandPeerID