Commit 216db146 authored by Jeromy's avatar Jeromy
Browse files

more vendoring

parent e1427950
package manet
import (
"net"
"testing"
ma "QmaA6aDzeHjZiuqBtgYRz8ZXb1qMCoyMHgyDjBEYQniUKF/go-multiaddr"
mautp "QmanZCL6SXRfafiUEMCBLq2QR171uQSdXQ8YAdHXLd8Cwr/go-multiaddr-net/utp"
)
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 TestFromUTP(t *testing.T) {
a := &net.UDPAddr{IP: net.ParseIP("10.20.30.40"), Port: 1234}
testConvert(t, "/ip4/10.20.30.40/udp/1234/utp", func() (ma.Multiaddr, error) {
return FromNetAddr(mautp.MakeAddr(a))
})
}
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/utp": 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,
"/ip6/::1/utp": false,
"/tcp/1234/ip4/1.2.3.4": false,
"/tcp/1234": false,
"/tcp/1234/utp": 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) {
test := func(e_maddr, e_nw, e_host string) {
m, err := ma.NewMultiaddr(e_maddr)
if err != nil {
t.Fatal("failed to construct", "/ip4/127.0.0.1/udp/1234", e_maddr)
}
nw, host, err := DialArgs(m)
if err != nil {
t.Fatal("failed to get dial args", e_maddr, m, err)
}
if nw != e_nw {
t.Error("failed to get udp network Dial Arg", e_nw, nw)
}
if host != e_host {
t.Error("failed to get host:port Dial Arg", e_host, host)
}
}
test("/ip4/127.0.0.1/udp/1234", "udp4", "127.0.0.1:1234")
test("/ip4/127.0.0.1/tcp/4321", "tcp4", "127.0.0.1:4321")
test("/ip4/127.0.0.1/udp/1234/utp", "utp4", "127.0.0.1:1234")
test("/ip6/::1/udp/1234", "udp6", "[::1]:1234")
test("/ip6/::1/tcp/4321", "tcp6", "[::1]:4321")
test("/ip6/::1/udp/1234/utp", "utp6", "[::1]:1234")
}
// Package manet provides Multiaddr specific versions of common
// functions in stdlib's net package. This means wrappers of
// standard net symbols like net.Dial and net.Listen, as well
// as conversion to/from net.Addr.
package manet
package manet
import (
"bytes"
ma "QmaA6aDzeHjZiuqBtgYRz8ZXb1qMCoyMHgyDjBEYQniUKF/go-multiaddr"
)
// Loopback Addresses
var (
// IP4Loopback is the ip4 loopback multiaddr
IP4Loopback = ma.StringCast("/ip4/127.0.0.1")
// IP6Loopback is the ip6 loopback multiaddr
IP6Loopback = ma.StringCast("/ip6/::1")
// IP6LinkLocalLoopback is the ip6 link-local loopback multiaddr
IP6LinkLocalLoopback = ma.StringCast("/ip6/fe80::1")
)
// Unspecified Addresses (used for )
var (
IP4Unspecified = ma.StringCast("/ip4/0.0.0.0")
IP6Unspecified = ma.StringCast("/ip6/::")
)
// 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
}
}
// IsIPLoopback returns whether a Multiaddr is a "Loopback" IP address
// This means either /ip4/127.0.0.1 or /ip6/::1
// TODO: differentiate IsIPLoopback and OverIPLoopback
func IsIPLoopback(m ma.Multiaddr) bool {
b := m.Bytes()
// /ip4/127 prefix (_entire_ /8 is loopback...)
if bytes.HasPrefix(b, []byte{ma.P_IP4, 127}) {
return true
}
// /ip6/::1
if IP6Loopback.Equal(m) || IP6LinkLocalLoopback.Equal(m) {
return true
}
return false
}
// IP6 Link Local addresses are non routable. The prefix is technically
// fe80::/10, but we test fe80::/16 for simplicity (no need to mask).
// So far, no hardware interfaces exist long enough to use those 2 bits.
// Send a PR if there is.
func IsIP6LinkLocal(m ma.Multiaddr) bool {
return bytes.HasPrefix(m.Bytes(), []byte{ma.P_IP6, 0xfe, 0x80})
}
// IsIPUnspecified returns whether a Multiaddr is am Unspecified IP address
// This means either /ip4/0.0.0.0 or /ip6/::
func IsIPUnspecified(m ma.Multiaddr) bool {
return IP4Unspecified.Equal(m) || IP6Unspecified.Equal(m)
}
package main
import (
"encoding/hex"
"flag"
"fmt"
"os"
ma "QmaA6aDzeHjZiuqBtgYRz8ZXb1qMCoyMHgyDjBEYQniUKF/go-multiaddr"
manet "QmanZCL6SXRfafiUEMCBLq2QR171uQSdXQ8YAdHXLd8Cwr/go-multiaddr-net"
)
// flags
var formats = []string{"string", "bytes", "hex", "slice"}
var format string
var hideLoopback bool
func init() {
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "usage: %s [<multiaddr>]\n\nFlags:\n", os.Args[0])
flag.PrintDefaults()
}
usage := fmt.Sprintf("output format, one of: %v", formats)
flag.StringVar(&format, "format", "string", usage)
flag.StringVar(&format, "f", "string", usage+" (shorthand)")
flag.BoolVar(&hideLoopback, "hide-loopback", false, "do not display loopback addresses")
}
func main() {
flag.Parse()
args := flag.Args()
if len(args) == 0 {
output(localAddresses()...)
} else {
output(address(args[0]))
}
}
func localAddresses() []ma.Multiaddr {
maddrs, err := manet.InterfaceMultiaddrs()
if err != nil {
die(err)
}
if !hideLoopback {
return maddrs
}
var maddrs2 []ma.Multiaddr
for _, a := range maddrs {
if !manet.IsIPLoopback(a) {
maddrs2 = append(maddrs2, a)
}
}
return maddrs2
}
func address(addr string) ma.Multiaddr {
m, err := ma.NewMultiaddr(addr)
if err != nil {
die(err)
}
return m
}
func output(ms ...ma.Multiaddr) {
for _, m := range ms {
fmt.Println(outfmt(m))
}
}
func outfmt(m ma.Multiaddr) string {
switch format {
case "string":
return m.String()
case "slice":
return fmt.Sprintf("%v", m.Bytes())
case "bytes":
return string(m.Bytes())
case "hex":
return "0x" + hex.EncodeToString(m.Bytes())
}
die("error: invalid format", format)
return ""
}
func die(v ...interface{}) {
fmt.Fprint(os.Stderr, v...)
fmt.Fprint(os.Stderr, "\n")
flag.Usage()
os.Exit(-1)
}
package manet
import (
"fmt"
"net"
ma "QmaA6aDzeHjZiuqBtgYRz8ZXb1qMCoyMHgyDjBEYQniUKF/go-multiaddr"
mautp "QmanZCL6SXRfafiUEMCBLq2QR171uQSdXQ8YAdHXLd8Cwr/go-multiaddr-net/utp"
)
// Conn is the equivalent of a net.Conn object. It is the
// result of calling the Dial or Listen functions in this
// package, with associated local and remote Multiaddrs.
type Conn interface {
net.Conn
// LocalMultiaddr returns the local Multiaddr associated
// with this connection
LocalMultiaddr() ma.Multiaddr
// RemoteMultiaddr returns the remote Multiaddr associated
// with this connection
RemoteMultiaddr() ma.Multiaddr
}
// WrapNetConn wraps a net.Conn object with a Multiaddr
// friendly Conn.
func WrapNetConn(nconn net.Conn) (Conn, error) {
if nconn == nil {
return nil, fmt.Errorf("failed to convert nconn.LocalAddr: nil")
}
laddr, err := FromNetAddr(nconn.LocalAddr())
if err != nil {
return nil, fmt.Errorf("failed to convert nconn.LocalAddr: %s", err)
}
raddr, err := FromNetAddr(nconn.RemoteAddr())
if err != nil {
return nil, fmt.Errorf("failed to convert nconn.RemoteAddr: %s", err)
}
return &maConn{
Conn: nconn,
laddr: laddr,
raddr: raddr,
}, nil
}
// maConn implements the Conn interface. It's a thin wrapper
// around a net.Conn
type maConn struct {
net.Conn
laddr ma.Multiaddr
raddr ma.Multiaddr
}
// LocalMultiaddr returns the local address associated with
// this connection
func (c *maConn) LocalMultiaddr() ma.Multiaddr {
return c.laddr
}
// RemoteMultiaddr returns the remote address associated with
// this connection
func (c *maConn) RemoteMultiaddr() ma.Multiaddr {
return c.raddr
}
// Dialer contains options for connecting to an address. It
// is effectively the same as net.Dialer, but its LocalAddr
// and RemoteAddr options are Multiaddrs, instead of net.Addrs.
type Dialer struct {
// Dialer is just an embedded net.Dialer, with all its options.
net.Dialer
// LocalAddr is the local address to use when dialing an
// address. The address must be of a compatible type for the
// network being dialed.
// If nil, a local address is automatically chosen.
LocalAddr ma.Multiaddr
}
// Dial connects to a remote address, using the options of the
// Dialer. Dialer uses an underlying net.Dialer to Dial a
// net.Conn, then wraps that in a Conn object (with local and
// remote Multiaddrs).
func (d *Dialer) Dial(remote ma.Multiaddr) (Conn, error) {
// if a LocalAddr is specified, use it on the embedded dialer.
if d.LocalAddr != nil {
// convert our multiaddr to net.Addr friendly
naddr, err := ToNetAddr(d.LocalAddr)
if err != nil {
return nil, err
}
// set the dialer's LocalAddr as naddr
d.Dialer.LocalAddr = naddr
}
// get the net.Dial friendly arguments from the remote addr
rnet, rnaddr, err := DialArgs(remote)
if err != nil {
return nil, err
}
// ok, Dial!
var nconn net.Conn
switch rnet {
case "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6":
nconn, err = d.Dialer.Dial(rnet, rnaddr)
if err != nil {
return nil, err
}
case "utp", "utp4", "utp6":
utpd := mautp.Dialer{
Timeout: d.Timeout,
LocalAddr: d.Dialer.LocalAddr,
}
// construct utp dialer, with options on our net.Dialer
nconn, err = utpd.Dial(rnet, rnaddr)
if err != nil {
return nil, err
}
}
// get local address (pre-specified or assigned within net.Conn)
local := d.LocalAddr
if local == nil {
local, err = FromNetAddr(nconn.LocalAddr())
if err != nil {
return nil, err
}
}
return &maConn{
Conn: nconn,
laddr: local,
raddr: remote,
}, nil
}
// Dial connects to a remote address. It uses an underlying net.Conn,
// then wraps it in a Conn object (with local and remote Multiaddrs).
func Dial(remote ma.Multiaddr) (Conn, error) {
return (&Dialer{}).Dial(remote)
}
// A Listener is a generic network listener for stream-oriented protocols.
// it uses an embedded net.Listener, overriding net.Listener.Accept to
// return a Conn and providing Multiaddr.
type Listener interface {
// NetListener returns the embedded net.Listener. Use with caution.
NetListener() net.Listener
// Accept waits for and returns the next connection to the listener.
// Returns a Multiaddr friendly Conn
Accept() (Conn, error)
// Close closes the listener.
// Any blocked Accept operations will be unblocked and return errors.
Close() error
// Multiaddr returns the listener's (local) Multiaddr.
Multiaddr() ma.Multiaddr
// Addr returns the net.Listener's network address.
Addr() net.Addr
}
// maListener implements Listener
type maListener struct {
net.Listener
laddr ma.Multiaddr
}
// NetListener returns the embedded net.Listener. Use with caution.
func (l *maListener) NetListener() net.Listener {
return l.Listener
}
// Accept waits for and returns the next connection to the listener.
// Returns a Multiaddr friendly Conn
func (l *maListener) Accept() (Conn, error) {
nconn, err := l.Listener.Accept()
if err != nil {
return nil, err
}
raddr, err := FromNetAddr(nconn.RemoteAddr())
if err != nil {
return nil, fmt.Errorf("failed to convert connn.RemoteAddr: %s", err)
}
return &maConn{
Conn: nconn,
laddr: l.laddr,
raddr: raddr,
}, nil
}
// Multiaddr returns the listener's (local) Multiaddr.
func (l *maListener) Multiaddr() ma.Multiaddr {
return l.laddr
}
// Addr returns the listener's network address.
func (l *maListener) Addr() net.Addr {
return l.Listener.Addr()
}
// Listen announces on the local network address laddr.
// The Multiaddr must be a "ThinWaist" stream-oriented network:
// ip4/tcp, ip6/tcp, (TODO: unix, unixpacket)
// See Dial for the syntax of laddr.
func Listen(laddr ma.Multiaddr) (Listener, error) {
// get the net.Listen friendly arguments from the remote addr
lnet, lnaddr, err := DialArgs(laddr)
if err != nil {
return nil, err
}
var nl net.Listener
switch lnet {
case "utp", "utp4", "utp6":
nl, err = mautp.Listen(lnet, lnaddr)
default:
nl, err = net.Listen(lnet, lnaddr)
}
if err != nil {
return nil, err
}
// we want to fetch the new multiaddr from the listener, as it may
// have resolved to some other value. WrapNetListener does it for us.
return WrapNetListener(nl)
}
// WrapNetListener wraps a net.Listener with a manet.Listener.
func WrapNetListener(nl net.Listener) (Listener, error) {
laddr, err := FromNetAddr(nl.Addr())
if err != nil {
return nil, err
}
return &maListener{
Listener: nl,
laddr: laddr,
}, nil
}
// InterfaceMultiaddrs will return the addresses matching net.InterfaceAddrs
func InterfaceMultiaddrs() ([]ma.Multiaddr, error) {
addrs, err := net.InterfaceAddrs()
if err != nil {
return nil, err
}
maddrs := make([]ma.Multiaddr, len(addrs))
for i, a := range addrs {
maddrs[i], err = FromNetAddr(a)
if err != nil {
return nil, err
}
}
return maddrs, nil
}
// AddrMatch returns the Multiaddrs that match the protocol stack on addr
func AddrMatch(match ma.Multiaddr, addrs []ma.Multiaddr) []ma.Multiaddr {
// we should match transports entirely.
p1s := match.Protocols()
out := make([]ma.Multiaddr, 0, len(addrs))
for _, a := range addrs {
p2s := a.Protocols()
if len(p1s) != len(p2s) {
continue
}
match := true
for i, p2 := range p2s {
if p1s[i].Code != p2.Code {
match = false
break
}
}
if match {
out = append(out, a)
}
}
return out
}
package manet
import (
"bytes"
"fmt"
"net"
"sync"
"testing"
ma "QmaA6aDzeHjZiuqBtgYRz8ZXb1qMCoyMHgyDjBEYQniUKF/go-multiaddr"
)
func newMultiaddr(t *testing.T, m string) ma.Multiaddr {
maddr, err := ma.NewMultiaddr(m)
if err != nil {
t.Fatal("failed to construct multiaddr:", m, err)
}
return maddr
}
func TestDial(t *testing.T) {
listener, err := net.Listen("tcp", "127.0.0.1:4321")
if err != nil {
t.Fatal("failed to listen")
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
cB, err := listener.Accept()
if err != nil {
t.Fatal("failed to accept")
}
// echo out
buf := make([]byte, 1024)
for {
_, err := cB.Read(buf)
if err != nil {
break
}
cB.Write(buf)
}
wg.Done()
}()
maddr := newMultiaddr(t, "/ip4/127.0.0.1/tcp/4321")
cA, err := Dial(maddr)
if err != nil {
t.Fatal("failed to dial")
}
buf := make([]byte, 1024)
if _, err := cA.Write([]byte("beep boop")); err != nil {
t.Fatal("failed to write:", err)
}
if _, err := cA.Read(buf); err != nil {
t.Fatal("failed to read:", buf, err)
}
if !bytes.Equal(buf[:9], []byte("beep boop")) {
t.Fatal("failed to echo:", buf)
}
maddr2 := cA.RemoteMultiaddr()
if !maddr2.Equal(maddr) {
t.Fatal("remote multiaddr not equal:", maddr, maddr2)
}
cA.Close()
wg.Wait()
}
func TestListen(t *testing.T) {
maddr := newMultiaddr(t, "/ip4/127.0.0.1/tcp/4322")
listener, err := Listen(maddr)
if err != nil {
t.Fatal("failed to listen")
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
cB, err := listener.Accept()
if err != nil {
t.Fatal("failed to accept")
}
if !cB.LocalMultiaddr().Equal(maddr) {
t.Fatal("local multiaddr not equal:", maddr, cB.LocalMultiaddr())
}
// echo out
buf := make([]byte, 1024)
for {
_, err := cB.Read(buf)
if err != nil {
break
}
cB.Write(buf)
}
wg.Done()
}()
cA, err := net.Dial("tcp", "127.0.0.1:4322")
if err != nil {
t.Fatal("failed to dial")
}
buf := make([]byte, 1024)
if _, err := cA.Write([]byte("beep boop")); err != nil {
t.Fatal("failed to write:", err)
}
if _, err := cA.Read(buf); err != nil {
t.Fatal("failed to read:", buf, err)
}
if !bytes.Equal(buf[:9], []byte("beep boop")) {
t.Fatal("failed to echo:", buf)
}
maddr2, err := FromNetAddr(cA.RemoteAddr())
if err != nil {
t.Fatal("failed to convert", err)
}
if !maddr2.Equal(maddr) {
t.Fatal("remote multiaddr not equal:", maddr, maddr2)
}
cA.Close()
wg.Wait()
}
func TestListenAddrs(t *testing.T) {
test := func(addr, resaddr string, succeed bool) {
if resaddr == "" {
resaddr = addr
}
maddr := newMultiaddr(t, addr)
l, err := Listen(maddr)
if !succeed {
if err == nil {
t.Fatal("succeeded in listening", addr)
}
return
}
if succeed && err != nil {
t.Error("failed to listen", addr, err)
}
if l == nil {
t.Error("failed to listen", addr, succeed, err)
}
if l.Multiaddr().String() != resaddr {
t.Error("listen addr did not resolve properly", l.Multiaddr().String(), resaddr, succeed, err)
}
if err = l.Close(); err != nil {
t.Fatal("failed to close listener", addr, err)
}
}
test("/ip4/127.0.0.1/tcp/4324", "", true)
test("/ip4/127.0.0.1/udp/4325", "", false)
test("/ip4/127.0.0.1/udp/4326/udt", "", false)
test("/ip4/0.0.0.0/tcp/4324", "", true)
test("/ip4/0.0.0.0/udp/4325", "", false)
test("/ip4/0.0.0.0/udp/4326/udt", "", false)
test("/ip6/::1/tcp/4324", "", true)
test("/ip6/::1/udp/4325", "", false)
test("/ip6/::1/udp/4326/udt", "", false)
test("/ip6/::/tcp/4324", "", true)
test("/ip6/::/udp/4325", "", false)
test("/ip6/::/udp/4326/udt", "", false)
// test("/ip4/127.0.0.1/udp/4326/utp", true)
}
func TestListenAndDial(t *testing.T) {
maddr := newMultiaddr(t, "/ip4/127.0.0.1/tcp/4323")
listener, err := Listen(maddr)
if err != nil {
t.Fatal("failed to listen")
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
cB, err := listener.Accept()
if err != nil {
t.Fatal("failed to accept")
}
if !cB.LocalMultiaddr().Equal(maddr) {
t.Fatal("local multiaddr not equal:", maddr, cB.LocalMultiaddr())
}
// echo out
buf := make([]byte, 1024)
for {
_, err := cB.Read(buf)
if err != nil {
break
}
cB.Write(buf)
}
wg.Done()
}()
cA, err := Dial(newMultiaddr(t, "/ip4/127.0.0.1/tcp/4323"))
if err != nil {
t.Fatal("failed to dial")
}
buf := make([]byte, 1024)
if _, err := cA.Write([]byte("beep boop")); err != nil {
t.Fatal("failed to write:", err)
}
if _, err := cA.Read(buf); err != nil {
t.Fatal("failed to read:", buf, err)
}
if !bytes.Equal(buf[:9], []byte("beep boop")) {
t.Fatal("failed to echo:", buf)
}
maddr2 := cA.RemoteMultiaddr()
if !maddr2.Equal(maddr) {
t.Fatal("remote multiaddr not equal:", maddr, maddr2)
}
cA.Close()
wg.Wait()
}
func TestListenAndDialUTP(t *testing.T) {
maddr := newMultiaddr(t, "/ip4/127.0.0.1/udp/4323/utp")
listener, err := Listen(maddr)
if err != nil {
t.Fatal("failed to listen: ", err)
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
cB, err := listener.Accept()
if err != nil {
t.Fatal("failed to accept")
}
if !cB.LocalMultiaddr().Equal(maddr) {
t.Fatal("local multiaddr not equal:", maddr, cB.LocalMultiaddr())
}
defer cB.Close()
// echo out
buf := make([]byte, 1024)
for {
_, err := cB.Read(buf)
if err != nil {
break
}
cB.Write(buf)
}
wg.Done()
}()
cA, err := Dial(newMultiaddr(t, "/ip4/127.0.0.1/udp/4323/utp"))
if err != nil {
t.Fatal("failed to dial", err)
}
buf := make([]byte, 1024)
if _, err := cA.Write([]byte("beep boop")); err != nil {
t.Fatal("failed to write:", err)
}
if _, err := cA.Read(buf); err != nil {
t.Fatal("failed to read:", buf, err)
}
if !bytes.Equal(buf[:9], []byte("beep boop")) {
t.Fatal("failed to echo:", buf)
}
maddr2 := cA.RemoteMultiaddr()
if !maddr2.Equal(maddr) {
t.Fatal("remote multiaddr not equal:", maddr, maddr2)
}
cA.Close()
wg.Wait()
}
func TestIPLoopback(t *testing.T) {
if IP4Loopback.String() != "/ip4/127.0.0.1" {
t.Error("IP4Loopback incorrect:", IP4Loopback)
}
if IP6Loopback.String() != "/ip6/::1" {
t.Error("IP6Loopback incorrect:", IP6Loopback)
}
if IP6LinkLocalLoopback.String() != "/ip6/fe80::1" {
t.Error("IP6LinkLocalLoopback incorrect:", IP6Loopback)
}
if !IsIPLoopback(IP4Loopback) {
t.Error("IsIPLoopback failed (IP4Loopback)")
}
if !IsIPLoopback(IP6Loopback) {
t.Error("IsIPLoopback failed (IP6Loopback)")
}
if !IsIPLoopback(IP6LinkLocalLoopback) {
t.Error("IsIPLoopback failed (IP6LinkLocalLoopback)")
}
}
func TestIPUnspecified(t *testing.T) {
if IP4Unspecified.String() != "/ip4/0.0.0.0" {
t.Error("IP4Unspecified incorrect:", IP4Unspecified)
}
if IP6Unspecified.String() != "/ip6/::" {
t.Error("IP6Unspecified incorrect:", IP6Unspecified)
}
if !IsIPUnspecified(IP4Unspecified) {
t.Error("IsIPUnspecified failed (IP4Unspecified)")
}
if !IsIPUnspecified(IP6Unspecified) {
t.Error("IsIPUnspecified failed (IP6Unspecified)")
}
}
func TestIP6LinkLocal(t *testing.T) {
if !IsIP6LinkLocal(IP6LinkLocalLoopback) {
t.Error("IsIP6LinkLocal failed (IP6LinkLocalLoopback)")
}
for a := 0; a < 65536; a++ {
isLinkLocal := (a == 0xfe80)
m := newMultiaddr(t, fmt.Sprintf("/ip6/%x::1", a))
if IsIP6LinkLocal(m) != isLinkLocal {
t.Error("IsIP6LinkLocal failed (%s != %v)", m, isLinkLocal)
}
}
}
func TestConvertNetAddr(t *testing.T) {
m1 := newMultiaddr(t, "/ip4/1.2.3.4/tcp/4001")
n1, err := ToNetAddr(m1)
if err != nil {
t.Fatal(err)
}
m2, err := FromNetAddr(n1)
if err != nil {
t.Fatal(err)
}
if m1.String() != m2.String() {
t.Fatal("ToNetAddr + FromNetAddr did not work")
}
}
func TestWrapNetConn(t *testing.T) {
// test WrapNetConn nil
if _, err := WrapNetConn(nil); err == nil {
t.Error("WrapNetConn(nil) should return an error")
}
checkErr := func(err error, s string) {
if err != nil {
t.Fatal(s, err)
}
}
listener, err := net.Listen("tcp", "127.0.0.1:0")
checkErr(err, "failed to listen")
var wg sync.WaitGroup
defer wg.Wait()
wg.Add(1)
go func() {
defer wg.Done()
cB, err := listener.Accept()
checkErr(err, "failed to accept")
cB.Close()
}()
cA, err := net.Dial("tcp", listener.Addr().String())
checkErr(err, "failed to dial")
defer cA.Close()
lmaddr, err := FromNetAddr(cA.LocalAddr())
checkErr(err, "failed to get local addr")
rmaddr, err := FromNetAddr(cA.RemoteAddr())
checkErr(err, "failed to get remote addr")
mcA, err := WrapNetConn(cA)
checkErr(err, "failed to wrap conn")
if mcA.LocalAddr().String() != cA.LocalAddr().String() {
t.Error("wrapped conn local addr differs")
}
if mcA.RemoteAddr().String() != cA.RemoteAddr().String() {
t.Error("wrapped conn remote addr differs")
}
if mcA.LocalMultiaddr().String() != lmaddr.String() {
t.Error("wrapped conn local maddr differs")
}
if mcA.RemoteMultiaddr().String() != rmaddr.String() {
t.Error("wrapped conn remote maddr differs")
}
}
func TestAddrMatch(t *testing.T) {
test := func(m ma.Multiaddr, input, expect []ma.Multiaddr) {
actual := AddrMatch(m, input)
testSliceEqual(t, expect, actual)
}
a := []ma.Multiaddr{
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/2345"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/tcp/2345"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/tcp/2345"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/udp/1234"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/udp/1234"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/ip6/::1"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/ip6/::1"),
newMultiaddr(t, "/ip6/::1/tcp/1234"),
newMultiaddr(t, "/ip6/::1/tcp/2345"),
newMultiaddr(t, "/ip6/::1/tcp/1234/tcp/2345"),
newMultiaddr(t, "/ip6/::1/tcp/1234/tcp/2345"),
newMultiaddr(t, "/ip6/::1/tcp/1234/udp/1234"),
newMultiaddr(t, "/ip6/::1/tcp/1234/udp/1234"),
newMultiaddr(t, "/ip6/::1/tcp/1234/ip6/::1"),
newMultiaddr(t, "/ip6/::1/tcp/1234/ip6/::1"),
}
test(a[0], a, []ma.Multiaddr{
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/2345"),
})
test(a[2], a, []ma.Multiaddr{
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/tcp/2345"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/tcp/2345"),
})
test(a[4], a, []ma.Multiaddr{
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/udp/1234"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/udp/1234"),
})
test(a[6], a, []ma.Multiaddr{
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/ip6/::1"),
newMultiaddr(t, "/ip4/1.2.3.4/tcp/1234/ip6/::1"),
})
test(a[8], a, []ma.Multiaddr{
newMultiaddr(t, "/ip6/::1/tcp/1234"),
newMultiaddr(t, "/ip6/::1/tcp/2345"),
})
test(a[10], a, []ma.Multiaddr{
newMultiaddr(t, "/ip6/::1/tcp/1234/tcp/2345"),
newMultiaddr(t, "/ip6/::1/tcp/1234/tcp/2345"),
})
test(a[12], a, []ma.Multiaddr{
newMultiaddr(t, "/ip6/::1/tcp/1234/udp/1234"),
newMultiaddr(t, "/ip6/::1/tcp/1234/udp/1234"),
})
test(a[14], a, []ma.Multiaddr{
newMultiaddr(t, "/ip6/::1/tcp/1234/ip6/::1"),
newMultiaddr(t, "/ip6/::1/tcp/1234/ip6/::1"),
})
}
func testSliceEqual(t *testing.T, a, b []ma.Multiaddr) {
if len(a) != len(b) {
t.Error("differ", a, b)
}
for i, addrA := range a {
if !addrA.Equal(b[i]) {
t.Error("differ", a, b)
}
}
}
{
"name": "go-multiaddr-net",
"author": "whyrusleeping",
"version": "1.0.0",
"gxDependencies": [
{
"name": "go-utp",
"hash": "QmVBEPpwYNGb5xQW6jPzYgV86KSPRrzhe4hA7o7mtAHZsT",
"version": "1.0.0"
},
{
"name": "go-multiaddr",
"hash": "QmaA6aDzeHjZiuqBtgYRz8ZXb1qMCoyMHgyDjBEYQniUKF",
"version": "1.0.0"
},
{
"name": "go-multihash",
"hash": "QmdeauTdyf38KDQB4Cc4CurPWRRb5pej27NCXPA7kbPTJy",
"version": "1.0.0"
}
],
"language": "go",
"gx": {
"dvcsimport": "github.com/jbenet/go-multiaddr-net"
}
}
\ No newline at end of file
package utp
import (
"errors"
"net"
"time"
utp "QmVBEPpwYNGb5xQW6jPzYgV86KSPRrzhe4hA7o7mtAHZsT/go-utp"
)
type Listener struct {
*utp.Socket
}
type Conn struct {
net.Conn
}
type Addr struct {
net string
child net.Addr
}
func (ca *Addr) Network() string {
return ca.net
}
func (ca *Addr) String() string {
return ca.child.String()
}
func (ca *Addr) Child() net.Addr {
return ca.child
}
func MakeAddr(a net.Addr) net.Addr {
return &Addr{
net: "utp",
child: a,
}
}
func ResolveAddr(network string, host string) (net.Addr, error) {
a, err := net.ResolveUDPAddr("udp"+network[3:], host)
if err != nil {
return nil, err
}
return MakeAddr(a), nil
}
func (u *Conn) LocalAddr() net.Addr {
return MakeAddr(u.Conn.LocalAddr())
}
func (u *Conn) RemoteAddr() net.Addr {
return MakeAddr(u.Conn.RemoteAddr())
}
func Listen(network string, laddr string) (net.Listener, error) {
switch network {
case "utp", "utp4", "utp6":
s, err := utp.NewSocket("udp"+network[3:], laddr)
if err != nil {
return nil, err
}
return &Listener{s}, nil
default:
return nil, errors.New("unrecognized network: " + network)
}
}
func (u *Listener) Accept() (net.Conn, error) {
c, err := u.Socket.Accept()
if err != nil {
return nil, err
}
return &Conn{c}, nil
}
func (u *Listener) Addr() net.Addr {
return MakeAddr(u.Socket.Addr())
}
type Dialer struct {
Timeout time.Duration
LocalAddr net.Addr
}
func (d *Dialer) Dial(rnet string, raddr string) (net.Conn, error) {
if d.LocalAddr != nil {
s, err := utp.NewSocket(d.LocalAddr.Network(), d.LocalAddr.String())
if err != nil {
return nil, err
}
// zero timeout is the same as calling s.Dial()
return s.DialTimeout(raddr, d.Timeout)
}
return utp.DialTimeout(raddr, d.Timeout)
}
package jitter
import (
"math/rand"
"time"
)
func Duration(average, plusMinus time.Duration) (ret time.Duration) {
ret = average - plusMinus
ret += time.Duration(rand.Int63n(2*int64(plusMinus) + 1))
return
}
package jitter
import "testing"
func TestZeroDuration(t *testing.T) {
if Duration(0, 0) != 0 {
t.FailNow()
}
}
{
"name": "jitter",
"author": "whyrusleeping",
"version": "1.0.0",
"language": "go",
"gx": {
"dvcsimport": "github.com/anacrolix/jitter"
}
}
\ No newline at end of file
language: go
go:
- 1.3
- release
- tip
script:
- make test
env: TEST_VERBOSE=1
The MIT License (MIT)
Copyright (c) 2014 Juan Batiz-Benet
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
test: go_test other_tests
other_tests:
cd test && make test
go_test: go_deps
go test -race -cpu=5 -v ./...
go_deps:
go get golang.org/x/crypto/sha3
go get github.com/jbenet/go-base58
# go-multihash
![travis](https://travis-ci.org/jbenet/go-multihash.svg)
[multihash](//github.com/jbenet/multihash) implementation in Go.
## Example
```go
package main
import (
"encoding/hex"
"fmt"
"github.com/jbenet/go-multihash"
)
func main() {
// ignores errors for simplicity.
// don't do that at home.
buf, _ := hex.DecodeString("0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33")
mhbuf, _ := multihash.EncodeName(buf, "sha1");
mhhex := hex.EncodeToString(mhbuf)
fmt.Printf("hex: %v\n", mhhex);
o, _ := multihash.Decode(mhbuf);
mhhex = hex.EncodeToString(o.Digest);
fmt.Printf("obj: %v 0x%x %d %s\n", o.Name, o.Code, o.Length, mhhex);
}
```
Run [test/foo.go](test/foo.go)
```
> cd test/
> go build
> ./test
hex: 11140beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
obj: sha1 0x11 20 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
```
## License
MIT
package multihash
import (
"fmt"
"io"
)
// Reader is an io.Reader wrapper that exposes a function
// to read a whole multihash, parse it, and return it.
type Reader interface {
io.Reader
ReadMultihash() (Multihash, error)
}
// Writer is an io.Writer wrapper that exposes a function
// to write a whole multihash.
type Writer interface {
io.Writer
WriteMultihash(Multihash) error
}
// NewReader wraps an io.Reader with a multihash.Reader
func NewReader(r io.Reader) Reader {
return &mhReader{r}
}
// NewWriter wraps an io.Writer with a multihash.Writer
func NewWriter(w io.Writer) Writer {
return &mhWriter{w}
}
type mhReader struct {
r io.Reader
}
func (r *mhReader) Read(buf []byte) (n int, err error) {
return r.r.Read(buf)
}
func (r *mhReader) ReadMultihash() (Multihash, error) {
mhhdr := make([]byte, 2)
if _, err := io.ReadFull(r.r, mhhdr); err != nil {
return nil, err
}
// first byte is the algo, the second is the length.
// (varints someday...)
length := uint(mhhdr[1])
if length > 127 {
return nil, fmt.Errorf("varints not yet supported (length is %d)", length)
}
buf := make([]byte, length+2)
buf[0] = mhhdr[0]
buf[1] = mhhdr[1]
if _, err := io.ReadFull(r.r, buf[2:]); err != nil {
return nil, err
}
return Cast(buf)
}
type mhWriter struct {
w io.Writer
}
func (w *mhWriter) Write(buf []byte) (n int, err error) {
return w.w.Write(buf)
}
func (w *mhWriter) WriteMultihash(m Multihash) error {
_, err := w.w.Write([]byte(m))
return err
}
package multihash
import (
"bytes"
"io"
"testing"
)
func TestReader(t *testing.T) {
var buf bytes.Buffer
for _, tc := range testCases {
m, err := tc.Multihash()
if err != nil {
t.Fatal(err)
}
buf.Write([]byte(m))
}
r := NewReader(&buf)
for _, tc := range testCases {
h, err := tc.Multihash()
if err != nil {
t.Fatal(err)
}
h2, err := r.ReadMultihash()
if err != nil {
t.Error(err)
continue
}
if !bytes.Equal(h, h2) {
t.Error("h and h2 should be equal")
}
}
}
func TestWriter(t *testing.T) {
var buf bytes.Buffer
w := NewWriter(&buf)
for _, tc := range testCases {
m, err := tc.Multihash()
if err != nil {
t.Error(err)
continue
}
if err := w.WriteMultihash(m); err != nil {
t.Error(err)
continue
}
buf2 := make([]byte, len(m))
if _, err := io.ReadFull(&buf, buf2); err != nil {
t.Error(err)
continue
}
if !bytes.Equal(m, buf2) {
t.Error("m and buf2 should be equal")
}
}
}
package multihash
import (
"encoding/hex"
"errors"
"fmt"
b58 "QmNsoHoCVhgXcv1Yg45jtkMgimxorTAN36fV9AQMFXHHAQ/go-base58"
)
// errors
var (
ErrUnknownCode = errors.New("unknown multihash code")
ErrTooShort = errors.New("multihash too short. must be > 3 bytes")
ErrTooLong = errors.New("multihash too long. must be < 129 bytes")
ErrLenNotSupported = errors.New("multihash does not yet support digests longer than 127 bytes")
)
// ErrInconsistentLen is returned when a decoded multihash has an inconsistent length
type ErrInconsistentLen struct {
dm *DecodedMultihash
}
func (e ErrInconsistentLen) Error() string {
return fmt.Sprintf("multihash length inconsistent: %v", e.dm)
}
// constants
const (
SHA1 = 0x11
SHA2_256 = 0x12
SHA2_512 = 0x13
SHA3 = 0x14
BLAKE2B = 0x40
BLAKE2S = 0x41
)
// Names maps the name of a hash to the code
var Names = map[string]int{
"sha1": SHA1,
"sha2-256": SHA2_256,
"sha2-512": SHA2_512,
"sha3": SHA3,
"blake2b": BLAKE2B,
"blake2s": BLAKE2S,
}
// Codes maps a hash code to it's name
var Codes = map[int]string{
SHA1: "sha1",
SHA2_256: "sha2-256",
SHA2_512: "sha2-512",
SHA3: "sha3",
BLAKE2B: "blake2b",
BLAKE2S: "blake2s",
}
// DefaultLengths maps a hash code to it's default length
var DefaultLengths = map[int]int{
SHA1: 20,
SHA2_256: 32,
SHA2_512: 64,
SHA3: 64,
BLAKE2B: 64,
BLAKE2S: 32,
}
type DecodedMultihash struct {
Code int
Name string
Length int
Digest []byte
}
type Multihash []byte
func (m *Multihash) HexString() string {
return hex.EncodeToString([]byte(*m))
}
func (m *Multihash) String() string {
return m.HexString()
}
func FromHexString(s string) (Multihash, error) {
b, err := hex.DecodeString(s)
if err != nil {
return Multihash{}, err
}
return Cast(b)
}
func (m Multihash) B58String() string {
return b58.Encode([]byte(m))
}
func FromB58String(s string) (m Multihash, err error) {
// panic handler, in case we try accessing bytes incorrectly.
defer func() {
if e := recover(); e != nil {
m = Multihash{}
err = e.(error)
}
}()
//b58 smells like it can panic...
b := b58.Decode(s)
return Cast(b)
}
func Cast(buf []byte) (Multihash, error) {
dm, err := Decode(buf)
if err != nil {
return Multihash{}, err
}
if !ValidCode(dm.Code) {
return Multihash{}, ErrUnknownCode
}
return Multihash(buf), nil
}
// Decode a hash from the given Multihash.
func Decode(buf []byte) (*DecodedMultihash, error) {
if len(buf) < 3 {
return nil, ErrTooShort
}
if len(buf) > 129 {
return nil, ErrTooLong
}
dm := &DecodedMultihash{
Code: int(uint8(buf[0])),
Name: Codes[int(uint8(buf[0]))],
Length: int(uint8(buf[1])),
Digest: buf[2:],
}
if len(dm.Digest) != dm.Length {
return nil, ErrInconsistentLen{dm}
}
return dm, nil
}
// Encode a hash digest along with the specified function code.
// Note: the length is derived from the length of the digest itself.
func Encode(buf []byte, code int) ([]byte, error) {
if !ValidCode(code) {
return nil, ErrUnknownCode
}
if len(buf) > 127 {
return nil, ErrLenNotSupported
}
pre := make([]byte, 2)
pre[0] = byte(uint8(code))
pre[1] = byte(uint8(len(buf)))
return append(pre, buf...), nil
}
func EncodeName(buf []byte, name string) ([]byte, error) {
return Encode(buf, Names[name])
}
// ValidCode checks whether a multihash code is valid.
func ValidCode(code int) bool {
if AppCode(code) {
return true
}
if _, ok := Codes[code]; ok {
return true
}
return false
}
// AppCode checks whether a multihash code is part of the App range.
func AppCode(code int) bool {
return code >= 0 && code < 0x10
}
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