diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index fa0b605b3442..1b6cfdfa3061 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -138,8 +138,8 @@ }, { "ImportPath": "github.com/jbenet/go-multiaddr", - "Comment": "0.1.2-34-g0d7b54b", - "Rev": "0d7b54ba432fda14bac37cdad717bd6270eacc85" + "Comment": "0.1.2-38-gc13f11b", + "Rev": "c13f11bbfe6439771f4df7bfb330f686826144e8" }, { "ImportPath": "github.com/jbenet/go-multiaddr-net", diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/.travis.yml b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/.travis.yml index 32ce5a786391..7b571f400428 100644 --- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/.travis.yml +++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/.travis.yml @@ -1,10 +1,9 @@ language: go go: - - 1.2 - 1.3 - release - tip script: - - go test -v ./... + - go test -race -cpu=5 -v ./... diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go index 03502e9dd708..a8a9b31c5cd7 100644 --- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go +++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go @@ -2,10 +2,13 @@ package multiaddr import ( "encoding/binary" + "errors" "fmt" "net" "strconv" "strings" + + mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" ) func stringToBytes(s string) ([]byte, error) { @@ -31,17 +34,19 @@ func stringToBytes(s string) ([]byte, error) { b = append(b, CodeToVarint(p.Code)...) sp = sp[1:] - if p.Size > 0 { - if len(sp) < 1 { - return nil, fmt.Errorf("protocol requires address, none given: %s", p.Name) - } - a, err := addressStringToBytes(p, sp[0]) - if err != nil { - return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err) - } - b = append(b, a...) - sp = sp[1:] + if p.Size == 0 { // no length. + continue + } + + if len(sp) < 1 { + return nil, fmt.Errorf("protocol requires address, none given: %s", p.Name) + } + a, err := addressStringToBytes(p, sp[0]) + if err != nil { + return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err) } + b = append(b, a...) + sp = sp[1:] } return b, nil } @@ -51,7 +56,14 @@ func bytesToString(b []byte) (ret string, err error) { defer func() { if e := recover(); e != nil { ret = "" - err = e.(error) + switch e := e.(type) { + case error: + err = e + case string: + err = errors.New(e) + default: + err = fmt.Errorf("%v", e) + } } }() @@ -65,20 +77,38 @@ func bytesToString(b []byte) (ret string, err error) { if p.Code == 0 { return "", fmt.Errorf("no protocol with code %d", code) } - s = strings.Join([]string{s, "/", p.Name}, "") + s += "/" + p.Name - if p.Size > 0 { - a := addressBytesToString(p, b[:(p.Size/8)]) - if len(a) > 0 { - s = strings.Join([]string{s, "/", a}, "") - } - b = b[(p.Size / 8):] + if p.Size == 0 { + continue + } + + size := sizeForAddr(p, b) + a, err := addressBytesToString(p, b[:size]) + if err != nil { + return "", err } + if len(a) > 0 { + s += "/" + a + } + b = b[size:] } return s, nil } +func sizeForAddr(p Protocol, b []byte) int { + switch { + case p.Size > 0: + return (p.Size / 8) + case p.Size == 0: + return 0 + default: + size, n := ReadVarintCode(b) + return size + n + } +} + func bytesSplit(b []byte) (ret [][]byte, err error) { // panic handler, in case we try accessing bytes incorrectly. defer func() { @@ -96,7 +126,8 @@ func bytesSplit(b []byte) (ret [][]byte, err error) { return [][]byte{}, fmt.Errorf("no protocol with code %d", b[0]) } - length := n + (p.Size / 8) + size := sizeForAddr(p, b[n:]) + length := n + size ret = append(ret, b[:length]) b = b[length:] } @@ -133,23 +164,46 @@ func addressStringToBytes(p Protocol, s string) ([]byte, error) { b := make([]byte, 2) binary.BigEndian.PutUint16(b, uint16(i)) return b, nil + + case P_IPFS: // ipfs + // the address is a varint prefixed multihash string representation + m, err := mh.FromB58String(s) + if err != nil { + return nil, fmt.Errorf("failed to parse ipfs addr: %s %s", s, err) + } + size := CodeToVarint(len(m)) + b := append(size, m...) + return b, nil } return []byte{}, fmt.Errorf("failed to parse %s addr: unknown", p.Name) } -func addressBytesToString(p Protocol, b []byte) string { +func addressBytesToString(p Protocol, b []byte) (string, error) { switch p.Code { // ipv4,6 case P_IP4, P_IP6: - return net.IP(b).String() + return net.IP(b).String(), nil // tcp udp dccp sctp case P_TCP, P_UDP, P_DCCP, P_SCTP: i := binary.BigEndian.Uint16(b) - return strconv.Itoa(int(i)) + return strconv.Itoa(int(i)), nil + + case P_IPFS: // ipfs + // the address is a varint-prefixed multihash string representation + size, n := ReadVarintCode(b) + b = b[n:] + if len(b) != size { + panic("inconsistent lengths") + } + m, err := mh.Cast(b) + if err != nil { + return "", err + } + return m.B58String(), nil } - return "" + return "", fmt.Errorf("unknown protocol") } diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go index 373c2c193735..1cb7ad4e9c9c 100644 --- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go +++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go @@ -64,6 +64,7 @@ func (m *multiaddr) Protocols() []Protocol { } }() + size := 0 ps := []Protocol{} b := m.bytes[:] for len(b) > 0 { @@ -75,7 +76,10 @@ func (m *multiaddr) Protocols() []Protocol { panic(fmt.Errorf("no protocol with code %d", b[0])) } ps = append(ps, p) - b = b[n+(p.Size/8):] + b = b[n:] + + size = sizeForAddr(p, b) + b = b[size:] } return ps } diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go index 654589764480..f0e9c36cf05b 100644 --- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go +++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go @@ -32,11 +32,13 @@ func TestConstructFails(t *testing.T) { "/ip4/127.0.0.1/udp", "/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa", "/ip4/127.0.0.1/tcp", + "/ip4/127.0.0.1/ipfs", + "/ip4/127.0.0.1/ipfs/tcp", } for _, a := range cases { if _, err := NewMultiaddr(a); err == nil { - t.Errorf("should have failed: %s", a) + t.Errorf("should have failed: %s - %s", a, err) } } } @@ -55,18 +57,24 @@ func TestConstructSucceeds(t *testing.T) { "/sctp/1234", "/udp/65535", "/tcp/65535", + "/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", "/udp/1234/sctp/1234", "/udp/1234/udt", "/udp/1234/utp", + "/tcp/1234/http", + "/tcp/1234/https", + "/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", "/ip4/127.0.0.1/udp/1234", "/ip4/127.0.0.1/udp/0", "/ip4/127.0.0.1/tcp/1234", "/ip4/127.0.0.1/tcp/1234/", + "/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC", + "/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234", } for _, a := range cases { if _, err := NewMultiaddr(a); err != nil { - t.Errorf("should have succeeded: %s", a) + t.Errorf("should have succeeded: %s -- %s", a, err) } } } diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.csv b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.csv index a8b1e3a47afd..213e9b52ba8b 100644 --- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.csv +++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.csv @@ -7,5 +7,6 @@ code size name 132 16 sctp 301 0 udt 302 0 utp +421 V ipfs 480 0 http 443 0 https diff --git a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.go b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.go index eaddc615ea36..c4ee5df7aa3e 100644 --- a/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.go +++ b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.go @@ -9,7 +9,7 @@ import ( // Protocol is a Multiaddr protocol description structure. type Protocol struct { Code int - Size int + Size int // a size of -1 indicates a length-prefixed variable size Name string VCode []byte } @@ -19,14 +19,22 @@ type Protocol struct { // 2. ensuring errors in the csv don't screw up code. // 3. changing a number has to happen in two places. const ( - P_IP4 = 4 - P_TCP = 6 - P_UDP = 17 - P_DCCP = 33 - P_IP6 = 41 - P_SCTP = 132 - P_UTP = 301 - P_UDT = 302 + P_IP4 = 4 + P_TCP = 6 + P_UDP = 17 + P_DCCP = 33 + P_IP6 = 41 + P_SCTP = 132 + P_UTP = 301 + P_UDT = 302 + P_IPFS = 421 + P_HTTP = 480 + P_HTTPS = 443 +) + +// These are special sizes +const ( + LengthPrefixedVarSize = -1 ) // Protocols is the list of multiaddr protocols supported by this module. @@ -40,8 +48,9 @@ var Protocols = []Protocol{ Protocol{P_SCTP, 16, "sctp", CodeToVarint(P_SCTP)}, Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP)}, Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT)}, - // {480, 0, "http"}, - // {443, 0, "https"}, + Protocol{P_HTTP, 0, "http", CodeToVarint(P_HTTP)}, + Protocol{P_HTTPS, 0, "https", CodeToVarint(P_HTTPS)}, + Protocol{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS)}, } // ProtocolWithName returns the Protocol description with given string name.