Commit f3f1f058 authored by Juan Batiz-Benet's avatar Juan Batiz-Benet
Browse files

swarm addr checks

parent 0c78255f
...@@ -9,6 +9,75 @@ import ( ...@@ -9,6 +9,75 @@ import (
manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net" manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr-net"
) )
// SupportedTransportStrings is the list of supported transports for the swarm.
// These are strings of encapsulated multiaddr protocols. E.g.:
// /ip4/tcp
var SupportedTransportStrings = []string{
"/ip4/tcp",
"/ip6/tcp",
// "/ip4/udp/utp", disabled because the lib is broken
// "/ip6/udp/utp", disabled because the lib is broken
// "/ip4/udp/udt", disabled because the lib doesnt work on arm
// "/ip6/udp/udt", disabled because the lib doesnt work on arm
}
// SupportedTransportProtocols is the list of supported transports for the swarm.
// These are []ma.Protocol lists. Populated at runtime from SupportedTransportStrings
var SupportedTransportProtocols = [][]ma.Protocol{}
func init() {
// initialize SupportedTransportProtocols
transports := make([][]ma.Protocol, len(SupportedTransportStrings))
for _, s := range SupportedTransportStrings {
t, err := ma.ProtocolsWithString(s)
if err != nil {
panic(err) // important to fix this in the codebase
}
transports = append(transports, t)
}
SupportedTransportProtocols = transports
}
// FilterAddrs is a filter that removes certain addresses
// from a list. the addresses removed are those known NOT
// to work with swarm. Namely, addresses with UTP.
func FilterAddrs(a []ma.Multiaddr) []ma.Multiaddr {
b := make([]ma.Multiaddr, 0, len(a))
for _, addr := range a {
if AddrUsable(addr) {
b = append(b, addr)
}
}
return b
}
// AddrUsable returns whether the swarm can use this addr.
func AddrUsable(a ma.Multiaddr) bool {
// test the address protocol list is in SupportedTransportProtocols
matches := func(a, b []ma.Protocol) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i].Code != b[i].Code {
return false
}
}
return true
}
transport := a.Protocols()
for _, supported := range SupportedTransportProtocols {
if matches(supported, transport) {
return true
}
}
return false
}
// ListenAddresses returns a list of addresses at which this swarm listens. // ListenAddresses returns a list of addresses at which this swarm listens.
func (s *Swarm) ListenAddresses() []ma.Multiaddr { func (s *Swarm) ListenAddresses() []ma.Multiaddr {
listeners := s.swarm.Listeners() listeners := s.swarm.Listeners()
......
package swarm
import (
"testing"
peer "github.com/jbenet/go-ipfs/p2p/peer"
testutil "github.com/jbenet/go-ipfs/util/testutil"
context "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/go.net/context"
ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
)
func TestFilterAddrs(t *testing.T) {
m := func(s string) ma.Multiaddr {
maddr, err := ma.NewMultiaddr(s)
if err != nil {
t.Fatal(err)
}
return maddr
}
bad := []ma.Multiaddr{
m("/ip4/1.2.3.4/udp/1234"), // unreliable
m("/ip4/1.2.3.4/udp/1234/sctp/1234"), // not in manet
m("/ip4/1.2.3.4/udp/1234/utp"), // utp is broken
m("/ip4/1.2.3.4/udp/1234/udt"), // udt is broken on arm
}
good := []ma.Multiaddr{
m("/ip4/127.0.0.1/tcp/1234"),
m("/ip6/::1/tcp/1234"),
}
goodAndBad := append(good, bad...)
// test filters
for _, a := range bad {
if AddrUsable(a) {
t.Errorf("addr %s should be unusable", a)
}
}
for _, a := range good {
if !AddrUsable(a) {
t.Errorf("addr %s should be usable", a)
}
}
subtestAddrsEqual(t, FilterAddrs(bad), []ma.Multiaddr{})
subtestAddrsEqual(t, FilterAddrs(good), good)
subtestAddrsEqual(t, FilterAddrs(goodAndBad), good)
// now test it with swarm
id, err := testutil.RandPeerID()
if err != nil {
t.Fatal(err)
}
ps := peer.NewPeerstore()
ctx := context.Background()
if _, err := NewNetwork(ctx, bad, id, ps); err == nil {
t.Fatal("should have failed to create swarm")
}
if _, err := NewNetwork(ctx, good, id, ps); err != nil {
t.Fatal("should have succeeded in creating swarm", err)
}
if _, err := NewNetwork(ctx, goodAndBad, id, ps); err == nil {
t.Fatal("should have failed to create swarm")
}
}
func subtestAddrsEqual(t *testing.T, a, b []ma.Multiaddr) {
if len(a) != len(b) {
t.Error(t)
}
in := func(addr ma.Multiaddr, l []ma.Multiaddr) bool {
for _, addr2 := range l {
if addr.Equal(addr2) {
return true
}
}
return false
}
for _, aa := range a {
if !in(aa, b) {
t.Errorf("%s not in %s", aa, b)
}
}
}
package swarm package swarm
import ( import (
"fmt"
conn "github.com/jbenet/go-ipfs/p2p/net/conn" conn "github.com/jbenet/go-ipfs/p2p/net/conn"
lgbl "github.com/jbenet/go-ipfs/util/eventlog/loggables" lgbl "github.com/jbenet/go-ipfs/util/eventlog/loggables"
...@@ -12,6 +14,13 @@ import ( ...@@ -12,6 +14,13 @@ import (
// Open listeners for each network the swarm should listen on // Open listeners for each network the swarm should listen on
func (s *Swarm) listen(addrs []ma.Multiaddr) error { func (s *Swarm) listen(addrs []ma.Multiaddr) error {
for _, addr := range addrs {
if !AddrUsable(addr) {
return fmt.Errorf("cannot use addr: %s", addr)
}
}
retErr := multierr.New() retErr := multierr.New()
// listen on every address // listen on every address
......
...@@ -36,3 +36,5 @@ func GenHostSwarm(t *testing.T, ctx context.Context) *bhost.BasicHost { ...@@ -36,3 +36,5 @@ func GenHostSwarm(t *testing.T, ctx context.Context) *bhost.BasicHost {
n := GenSwarmNetwork(t, ctx) n := GenSwarmNetwork(t, ctx)
return bhost.New(n) return bhost.New(n)
} }
var RandPeerID = tu.RandPeerID
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