mirror of
https://github.com/logos-messaging/go-multiaddr.git
synced 2026-01-03 21:43:06 +00:00
moved net stuff into subpkg
This commit is contained in:
commit
dc978d4bc3
152
convert.go
Normal file
152
convert.go
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
ma "github.com/jbenet/go-multiaddr"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errIncorrectNetAddr = fmt.Errorf("incorrect network addr conversion")
|
||||||
|
|
||||||
|
// FromNetAddr converts a net.Addr type to a Multiaddr.
|
||||||
|
func FromNetAddr(a net.Addr) (ma.Multiaddr, error) {
|
||||||
|
switch a.Network() {
|
||||||
|
case "tcp", "tcp4", "tcp6":
|
||||||
|
ac, ok := a.(*net.TCPAddr)
|
||||||
|
if !ok {
|
||||||
|
return nil, errIncorrectNetAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get IP Addr
|
||||||
|
ipm, err := FromIP(ac.IP)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errIncorrectNetAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get TCP Addr
|
||||||
|
tcpm, err := ma.NewMultiaddr(fmt.Sprintf("/tcp/%d", ac.Port))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errIncorrectNetAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encapsulate
|
||||||
|
return ipm.Encapsulate(tcpm), nil
|
||||||
|
|
||||||
|
case "udp", "upd4", "udp6":
|
||||||
|
ac, ok := a.(*net.UDPAddr)
|
||||||
|
if !ok {
|
||||||
|
return nil, errIncorrectNetAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get IP Addr
|
||||||
|
ipm, err := FromIP(ac.IP)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errIncorrectNetAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get UDP Addr
|
||||||
|
udpm, err := ma.NewMultiaddr(fmt.Sprintf("/udp/%d", ac.Port))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errIncorrectNetAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
// Encapsulate
|
||||||
|
return ipm.Encapsulate(udpm), nil
|
||||||
|
|
||||||
|
case "ip", "ip4", "ip6":
|
||||||
|
ac, ok := a.(*net.IPAddr)
|
||||||
|
if !ok {
|
||||||
|
return nil, errIncorrectNetAddr
|
||||||
|
}
|
||||||
|
return FromIP(ac.IP)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown network %v", a.Network())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToNetAddr converts a Multiaddr to a net.Addr
|
||||||
|
// Must be ThinWaist. acceptable protocol stacks are:
|
||||||
|
// /ip{4,6}/{tcp, udp}
|
||||||
|
func ToNetAddr(maddr ma.Multiaddr) (net.Addr, error) {
|
||||||
|
network, host, err := DialArgs(maddr)
|
||||||
|
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) (ma.Multiaddr, error) {
|
||||||
|
switch {
|
||||||
|
case ip.To4() != nil:
|
||||||
|
return ma.NewMultiaddr("/ip4/" + ip.String())
|
||||||
|
case ip.To16() != nil:
|
||||||
|
return ma.NewMultiaddr("/ip6/" + ip.String())
|
||||||
|
default:
|
||||||
|
return nil, errIncorrectNetAddr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DialArgs is a convenience function returning arguments for use in net.Dial
|
||||||
|
func DialArgs(m ma.Multiaddr) (string, string, error) {
|
||||||
|
if !IsThinWaist(m) {
|
||||||
|
return "", "", fmt.Errorf("%s is not a 'thin waist' address", m)
|
||||||
|
}
|
||||||
|
|
||||||
|
str := m.String()
|
||||||
|
parts := strings.Split(str, "/")[1:]
|
||||||
|
|
||||||
|
if len(parts) == 2 { // only IP
|
||||||
|
return parts[0], parts[1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
network := parts[2]
|
||||||
|
var host string
|
||||||
|
switch parts[0] {
|
||||||
|
case "ip4":
|
||||||
|
host = strings.Join([]string{parts[1], parts[3]}, ":")
|
||||||
|
case "ip6":
|
||||||
|
host = fmt.Sprintf("[%s]:%s", parts[1], parts[3])
|
||||||
|
}
|
||||||
|
return network, host, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols.
|
||||||
|
// This means: /{IP4, IP6}[/{TCP, UDP}]
|
||||||
|
func IsThinWaist(m ma.Multiaddr) bool {
|
||||||
|
p := m.Protocols()
|
||||||
|
|
||||||
|
// nothing? not even a waist.
|
||||||
|
if len(p) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if p[0].Code != ma.P_IP4 && p[0].Code != ma.P_IP6 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// only IP? still counts.
|
||||||
|
if len(p) == 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
switch p[1].Code {
|
||||||
|
case ma.P_TCP, ma.P_UDP, ma.P_IP4, ma.P_IP6:
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
137
convert_test.go
Normal file
137
convert_test.go
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package net
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
ma "github.com/jbenet/go-multiaddr"
|
||||||
|
)
|
||||||
|
|
||||||
|
type GenFunc func() (ma.Multiaddr, error)
|
||||||
|
|
||||||
|
func testConvert(t *testing.T, s string, gen GenFunc) {
|
||||||
|
m, err := gen()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("failed to generate.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s2 := m.String(); err != nil || s2 != s {
|
||||||
|
t.Fatal("failed to convert: " + s + " != " + s2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testToNetAddr(t *testing.T, maddr, ntwk, addr string) {
|
||||||
|
m, err := ma.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() (ma.Multiaddr, error) {
|
||||||
|
return FromIP(net.ParseIP("10.20.30.40"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromIP6(t *testing.T) {
|
||||||
|
testConvert(t, "/ip6/2001:4860:0:2001::68", func() (ma.Multiaddr, error) {
|
||||||
|
return FromIP(net.ParseIP("2001:4860:0:2001::68"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromTCP(t *testing.T) {
|
||||||
|
testConvert(t, "/ip4/10.20.30.40/tcp/1234", func() (ma.Multiaddr, error) {
|
||||||
|
return FromNetAddr(&net.TCPAddr{
|
||||||
|
IP: net.ParseIP("10.20.30.40"),
|
||||||
|
Port: 1234,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFromUDP(t *testing.T) {
|
||||||
|
testConvert(t, "/ip4/10.20.30.40/udp/1234", func() (ma.Multiaddr, error) {
|
||||||
|
return FromNetAddr(&net.UDPAddr{
|
||||||
|
IP: net.ParseIP("10.20.30.40"),
|
||||||
|
Port: 1234,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
m, err := ma.NewMultiaddr(a)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to construct Multiaddr: %s", a)
|
||||||
|
}
|
||||||
|
|
||||||
|
if IsThinWaist(m) != res {
|
||||||
|
t.Fatalf("IsThinWaist(%s) != %v", a, res)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDialArgs(t *testing.T) {
|
||||||
|
m, err := ma.NewMultiaddr("/ip4/127.0.0.1/udp/1234")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("failed to construct", "/ip4/127.0.0.1/udp/1234")
|
||||||
|
}
|
||||||
|
|
||||||
|
nw, host, err := DialArgs(m)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("failed to get dial args", "/ip4/127.0.0.1/udp/1234", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if nw != "udp" {
|
||||||
|
t.Error("failed to get udp network Dial Arg")
|
||||||
|
}
|
||||||
|
|
||||||
|
if host != "127.0.0.1:1234" {
|
||||||
|
t.Error("failed to get host:port Dial Arg")
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user