1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-09-10 22:49:13 +08:00

update multiaddr for ipfs addrs

This commit is contained in:
Juan Batiz-Benet
2015-01-20 12:29:02 -08:00
parent d0f60432d8
commit 6f9c297f08
7 changed files with 116 additions and 41 deletions

4
Godeps/Godeps.json generated
View File

@ -167,8 +167,8 @@
}, },
{ {
"ImportPath": "github.com/jbenet/go-multiaddr", "ImportPath": "github.com/jbenet/go-multiaddr",
"Comment": "0.1.2-34-g0d7b54b", "Comment": "0.1.2-38-gc13f11b",
"Rev": "0d7b54ba432fda14bac37cdad717bd6270eacc85" "Rev": "c13f11bbfe6439771f4df7bfb330f686826144e8"
}, },
{ {
"ImportPath": "github.com/jbenet/go-multiaddr-net", "ImportPath": "github.com/jbenet/go-multiaddr-net",

View File

@ -1,10 +1,9 @@
language: go language: go
go: go:
- 1.2
- 1.3 - 1.3
- release - release
- tip - tip
script: script:
- go test -v ./... - go test -race -cpu=5 -v ./...

View File

@ -2,10 +2,13 @@ package multiaddr
import ( import (
"encoding/binary" "encoding/binary"
"errors"
"fmt" "fmt"
"net" "net"
"strconv" "strconv"
"strings" "strings"
mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
) )
func stringToBytes(s string) ([]byte, error) { func stringToBytes(s string) ([]byte, error) {
@ -31,17 +34,19 @@ func stringToBytes(s string) ([]byte, error) {
b = append(b, CodeToVarint(p.Code)...) b = append(b, CodeToVarint(p.Code)...)
sp = sp[1:] sp = sp[1:]
if p.Size > 0 { if p.Size == 0 { // no length.
if len(sp) < 1 { continue
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 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 return b, nil
} }
@ -51,7 +56,14 @@ func bytesToString(b []byte) (ret string, err error) {
defer func() { defer func() {
if e := recover(); e != nil { if e := recover(); e != nil {
ret = "" 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 { if p.Code == 0 {
return "", fmt.Errorf("no protocol with code %d", code) return "", fmt.Errorf("no protocol with code %d", code)
} }
s = strings.Join([]string{s, "/", p.Name}, "") s += "/" + p.Name
if p.Size > 0 { if p.Size == 0 {
a := addressBytesToString(p, b[:(p.Size/8)]) continue
if len(a) > 0 {
s = strings.Join([]string{s, "/", a}, "")
}
b = b[(p.Size / 8):]
} }
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 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) { func bytesSplit(b []byte) (ret [][]byte, err error) {
// panic handler, in case we try accessing bytes incorrectly. // panic handler, in case we try accessing bytes incorrectly.
defer func() { 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]) 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]) ret = append(ret, b[:length])
b = b[length:] b = b[length:]
} }
@ -133,23 +164,46 @@ func addressStringToBytes(p Protocol, s string) ([]byte, error) {
b := make([]byte, 2) b := make([]byte, 2)
binary.BigEndian.PutUint16(b, uint16(i)) binary.BigEndian.PutUint16(b, uint16(i))
return b, nil 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) 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 { switch p.Code {
// ipv4,6 // ipv4,6
case P_IP4, P_IP6: case P_IP4, P_IP6:
return net.IP(b).String() return net.IP(b).String(), nil
// tcp udp dccp sctp // tcp udp dccp sctp
case P_TCP, P_UDP, P_DCCP, P_SCTP: case P_TCP, P_UDP, P_DCCP, P_SCTP:
i := binary.BigEndian.Uint16(b) 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")
} }

View File

@ -64,6 +64,7 @@ func (m *multiaddr) Protocols() []Protocol {
} }
}() }()
size := 0
ps := []Protocol{} ps := []Protocol{}
b := m.bytes[:] b := m.bytes[:]
for len(b) > 0 { for len(b) > 0 {
@ -75,7 +76,10 @@ func (m *multiaddr) Protocols() []Protocol {
panic(fmt.Errorf("no protocol with code %d", b[0])) panic(fmt.Errorf("no protocol with code %d", b[0]))
} }
ps = append(ps, p) ps = append(ps, p)
b = b[n+(p.Size/8):] b = b[n:]
size = sizeForAddr(p, b)
b = b[size:]
} }
return ps return ps
} }

View File

@ -32,11 +32,13 @@ func TestConstructFails(t *testing.T) {
"/ip4/127.0.0.1/udp", "/ip4/127.0.0.1/udp",
"/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa", "/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa",
"/ip4/127.0.0.1/tcp", "/ip4/127.0.0.1/tcp",
"/ip4/127.0.0.1/ipfs",
"/ip4/127.0.0.1/ipfs/tcp",
} }
for _, a := range cases { for _, a := range cases {
if _, err := NewMultiaddr(a); err == nil { 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", "/sctp/1234",
"/udp/65535", "/udp/65535",
"/tcp/65535", "/tcp/65535",
"/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"/udp/1234/sctp/1234", "/udp/1234/sctp/1234",
"/udp/1234/udt", "/udp/1234/udt",
"/udp/1234/utp", "/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/1234",
"/ip4/127.0.0.1/udp/0", "/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/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 { for _, a := range cases {
if _, err := NewMultiaddr(a); err != nil { if _, err := NewMultiaddr(a); err != nil {
t.Errorf("should have succeeded: %s", a) t.Errorf("should have succeeded: %s -- %s", a, err)
} }
} }
} }

View File

@ -7,5 +7,6 @@ code size name
132 16 sctp 132 16 sctp
301 0 udt 301 0 udt
302 0 utp 302 0 utp
421 V ipfs
480 0 http 480 0 http
443 0 https 443 0 https

1 code size name
7 132 16 sctp
8 301 0 udt
9 302 0 utp
10 421 V ipfs
11 480 0 http
12 443 0 https

View File

@ -9,7 +9,7 @@ import (
// Protocol is a Multiaddr protocol description structure. // Protocol is a Multiaddr protocol description structure.
type Protocol struct { type Protocol struct {
Code int Code int
Size int Size int // a size of -1 indicates a length-prefixed variable size
Name string Name string
VCode []byte VCode []byte
} }
@ -19,14 +19,22 @@ type Protocol struct {
// 2. ensuring errors in the csv don't screw up code. // 2. ensuring errors in the csv don't screw up code.
// 3. changing a number has to happen in two places. // 3. changing a number has to happen in two places.
const ( const (
P_IP4 = 4 P_IP4 = 4
P_TCP = 6 P_TCP = 6
P_UDP = 17 P_UDP = 17
P_DCCP = 33 P_DCCP = 33
P_IP6 = 41 P_IP6 = 41
P_SCTP = 132 P_SCTP = 132
P_UTP = 301 P_UTP = 301
P_UDT = 302 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. // 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_SCTP, 16, "sctp", CodeToVarint(P_SCTP)},
Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP)}, Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP)},
Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT)}, Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT)},
// {480, 0, "http"}, Protocol{P_HTTP, 0, "http", CodeToVarint(P_HTTP)},
// {443, 0, "https"}, 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. // ProtocolWithName returns the Protocol description with given string name.