From 351b5d0f147b24f0c7d04b059566cc7aca509444 Mon Sep 17 00:00:00 2001 From: Juan Batiz-Benet Date: Fri, 10 Oct 2014 20:31:19 -0700 Subject: [PATCH] ToNetAddr + tests. --- net.go | 47 ++++++++++++++++++++++++++++++++++---- net_test.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 5 deletions(-) diff --git a/net.go b/net.go index ed91dc2..cddebd0 100644 --- a/net.go +++ b/net.go @@ -65,6 +65,27 @@ func FromNetAddr(a net.Addr) (Multiaddr, error) { } } +// ToNetAddr converts a Multiaddr to a net.Addr +// Must be ThinWaist. acceptable protocol stacks are: +// /ip{4,6}/{tcp, udp} +func ToNetAddr(ma Multiaddr) (net.Addr, error) { + network, host, err := DialArgs(ma) + if err != nil { + return nil, err + } + + switch network { + case "tcp": + return net.ResolveTCPAddr(network, host) + case "udp": + return net.ResolveUDPAddr(network, host) + case "ip": + return net.ResolveIPAddr(network, host) + } + + return nil, fmt.Errorf("network not supported: %s", network) +} + // FromIP converts a net.IP type to a Multiaddr. func FromIP(ip net.IP) (Multiaddr, error) { switch { @@ -85,8 +106,12 @@ func DialArgs(m Multiaddr) (string, string, error) { str := m.String() parts := strings.Split(str, "/")[1:] - network := parts[2] + if len(parts) == 2 { // only IP + return parts[0], parts[1], nil + } + + network := parts[2] var host string switch parts[0] { case "ip4": @@ -98,16 +123,28 @@ func DialArgs(m Multiaddr) (string, string, error) { } // IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols. -// This means: /{IP4, IP6}/{TCP, UDP} +// This means: /{IP4, IP6}[/{TCP, UDP}] func IsThinWaist(m Multiaddr) bool { p := m.Protocols() + + // nothing? not even a waist. + if len(p) == 0 { + return false + } + if p[0].Code != P_IP4 && p[0].Code != P_IP6 { return false } - if p[1].Code != P_TCP && p[1].Code != P_UDP { - return false + // only IP? still counts. + if len(p) == 1 { + return true } - return true + switch p[1].Code { + case P_TCP, P_UDP, P_IP4, P_IP6: + return true + default: + return false + } } diff --git a/net_test.go b/net_test.go index c9cb4b4..5edb560 100644 --- a/net_test.go +++ b/net_test.go @@ -18,6 +18,44 @@ func testConvert(t *testing.T, s string, gen GenFunc) { } } +func testToNetAddr(t *testing.T, maddr, ntwk, addr string) { + m, err := NewMultiaddr(maddr) + if err != nil { + t.Fatal("failed to generate.") + } + + naddr, err := ToNetAddr(m) + if addr == "" { // should fail + if err == nil { + t.Fatalf("failed to error: %s", m) + } + return + } + + // shouldn't fail + if err != nil { + t.Fatalf("failed to convert to net addr: %s", m) + } + + if naddr.String() != addr { + t.Fatalf("naddr.Address() == %s != %s", naddr, addr) + } + + if naddr.Network() != ntwk { + t.Fatalf("naddr.Network() == %s != %s", naddr.Network(), ntwk) + } + + // should convert properly + switch ntwk { + case "tcp": + _ = naddr.(*net.TCPAddr) + case "udp": + _ = naddr.(*net.UDPAddr) + case "ip": + _ = naddr.(*net.IPAddr) + } +} + func TestFromIP4(t *testing.T) { testConvert(t, "/ip4/10.20.30.40", func() (Multiaddr, error) { return FromIP(net.ParseIP("10.20.30.40")) @@ -48,6 +86,34 @@ func TestFromUDP(t *testing.T) { }) } +func TestThinWaist(t *testing.T) { + addrs := map[string]bool{ + "/ip4/127.0.0.1/udp/1234": true, + "/ip4/127.0.0.1/tcp/1234": true, + "/ip4/127.0.0.1/udp/1234/tcp/1234": true, + "/ip4/127.0.0.1/tcp/12345/ip4/1.2.3.4": true, + "/ip6/::1/tcp/80": true, + "/ip6/::1/udp/80": true, + "/ip6/::1": true, + "/tcp/1234/ip4/1.2.3.4": false, + "/tcp/1234": false, + "/tcp/1234/udp/1234": false, + "/ip4/1.2.3.4/ip4/2.3.4.5": true, + "/ip6/::1/ip4/2.3.4.5": true, + } + + for a, res := range addrs { + ma, err := NewMultiaddr(a) + if err != nil { + t.Fatalf("failed to construct Multiaddr: %s", a) + } + + if IsThinWaist(ma) != res { + t.Fatalf("IsThinWaist(%s) != %v", a, res) + } + } +} + func TestDialArgs(t *testing.T) { m, err := NewMultiaddr("/ip4/127.0.0.1/udp/1234") if err != nil {