@cryptotaxi247 / kubo / commits / 06299297c

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