1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-06-29 17:36:38 +08:00

updated multiaddr

This commit is contained in:
Juan Batiz-Benet
2015-01-09 05:51:51 -08:00
parent 3bc976c49e
commit 19a5f088d5
8 changed files with 174 additions and 38 deletions

4
Godeps/Godeps.json generated
View File

@ -122,8 +122,8 @@
},
{
"ImportPath": "github.com/jbenet/go-multiaddr",
"Comment": "0.1.2-30-g99cf3ed",
"Rev": "99cf3edc711751cf7b43505fac0e3913f6b9a75c"
"Comment": "0.1.2-34-g0d7b54b",
"Rev": "0d7b54ba432fda14bac37cdad717bd6270eacc85"
},
{
"ImportPath": "github.com/jbenet/go-multiaddr-net",

View File

@ -28,9 +28,9 @@ m2.Equal(m1)
```go
// get the multiaddr protocol description objects
addr.Protocols()
// []*Protocol{
// &Protocol{ Code: 4, Name: 'ip4', Size: 32},
// &Protocol{ Code: 17, Name: 'udp', Size: 16},
// []Protocol{
// Protocol{ Code: 4, Name: 'ip4', Size: 32},
// Protocol{ Code: 17, Name: 'udp', Size: 16},
// }
```

View File

@ -25,14 +25,20 @@ func stringToBytes(s string) ([]byte, error) {
for len(sp) > 0 {
p := ProtocolWithName(sp[0])
if p == nil {
if p.Code == 0 {
return nil, fmt.Errorf("no protocol with name %s", sp[0])
}
b = append(b, CodeToVarint(p.Code)...)
sp = sp[1:]
if p.Size > 0 {
a := addressStringToBytes(p, sp[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:]
}
@ -56,7 +62,7 @@ func bytesToString(b []byte) (ret string, err error) {
code, n := ReadVarintCode(b)
b = b[n:]
p := ProtocolWithCode(code)
if p == nil {
if p.Code == 0 {
return "", fmt.Errorf("no protocol with code %d", code)
}
s = strings.Join([]string{s, "/", p.Name}, "")
@ -86,7 +92,7 @@ func bytesSplit(b []byte) (ret [][]byte, err error) {
for len(b) > 0 {
code, n := ReadVarintCode(b)
p := ProtocolWithCode(code)
if p == nil {
if p.Code == 0 {
return [][]byte{}, fmt.Errorf("no protocol with code %d", b[0])
}
@ -98,29 +104,41 @@ func bytesSplit(b []byte) (ret [][]byte, err error) {
return ret, nil
}
func addressStringToBytes(p *Protocol, s string) []byte {
func addressStringToBytes(p Protocol, s string) ([]byte, error) {
switch p.Code {
case P_IP4: // ipv4
return net.ParseIP(s).To4()
i := net.ParseIP(s).To4()
if i == nil {
return nil, fmt.Errorf("failed to parse ip4 addr: %s", s)
}
return i, nil
case P_IP6: // ipv6
return net.ParseIP(s).To16()
i := net.ParseIP(s).To16()
if i == nil {
return nil, fmt.Errorf("failed to parse ip6 addr: %s", s)
}
return i, nil
// tcp udp dccp sctp
case P_TCP, P_UDP, P_DCCP, P_SCTP:
b := make([]byte, 2)
i, err := strconv.Atoi(s)
if err == nil {
binary.BigEndian.PutUint16(b, uint16(i))
if err != nil {
return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, err)
}
return b
if i >= 65536 {
return nil, fmt.Errorf("failed to parse %s addr: %s", p.Name, "greater than 65536")
}
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, uint16(i))
return b, nil
}
return []byte{}
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 {
switch p.Code {
// ipv4,6

View File

@ -26,7 +26,7 @@ type Multiaddr interface {
// Protocols returns the list of Protocols this Multiaddr includes
// will panic if protocol code incorrect (and bytes accessed incorrectly)
Protocols() []*Protocol
Protocols() []Protocol
// Encapsulate wraps this Multiaddr around another. For example:
//

View File

@ -54,7 +54,7 @@ func (m *multiaddr) String() string {
// Protocols returns the list of protocols this Multiaddr has.
// will panic in case we access bytes incorrectly.
func (m *multiaddr) Protocols() []*Protocol {
func (m *multiaddr) Protocols() []Protocol {
// panic handler, in case we try accessing bytes incorrectly.
defer func() {
@ -64,12 +64,12 @@ func (m *multiaddr) Protocols() []*Protocol {
}
}()
ps := []*Protocol{}
ps := []Protocol{}
b := m.bytes[:]
for len(b) > 0 {
code, n := ReadVarintCode(b)
p := ProtocolWithCode(code)
if p == nil {
if p.Code == 0 {
// this is a panic (and not returning err) because this should've been
// caught on constructing the Multiaddr
panic(fmt.Errorf("no protocol with code %d", b[0]))

View File

@ -14,6 +14,63 @@ func newMultiaddr(t *testing.T, a string) Multiaddr {
return m
}
func TestConstructFails(t *testing.T) {
cases := []string{
"/ip4",
"/ip4/::1",
"/ip4/fdpsofodsajfdoisa",
"/ip6",
"/udp",
"/tcp",
"/sctp",
"/udp/65536",
"/tcp/65536",
"/udp/1234/sctp",
"/udp/1234/udt/1234",
"/udp/1234/utp/1234",
"/ip4/127.0.0.1/udp/jfodsajfidosajfoidsa",
"/ip4/127.0.0.1/udp",
"/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa",
"/ip4/127.0.0.1/tcp",
}
for _, a := range cases {
if _, err := NewMultiaddr(a); err == nil {
t.Errorf("should have failed: %s", a)
}
}
}
func TestConstructSucceeds(t *testing.T) {
cases := []string{
"/ip4/1.2.3.4",
"/ip4/0.0.0.0",
"/ip6/::1",
"/ip6/2601:9:4f81:9700:803e:ca65:66e8:c21",
"/udp/0",
"/tcp/0",
"/sctp/0",
"/udp/1234",
"/tcp/1234",
"/sctp/1234",
"/udp/65535",
"/tcp/65535",
"/udp/1234/sctp/1234",
"/udp/1234/udt",
"/udp/1234/utp",
"/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/",
}
for _, a := range cases {
if _, err := NewMultiaddr(a); err != nil {
t.Errorf("should have succeeded: %s", a)
}
}
}
func TestEqual(t *testing.T) {
m1 := newMultiaddr(t, "/ip4/127.0.0.1/udp/1234")
m2 := newMultiaddr(t, "/ip4/127.0.0.1/tcp/1234")
@ -147,18 +204,58 @@ func TestProtocols(t *testing.T) {
}
ps := m.Protocols()
if ps[0] != ProtocolWithName("ip4") {
if ps[0].Code != ProtocolWithName("ip4").Code {
t.Error(ps[0], ProtocolWithName("ip4"))
t.Error("failed to get ip4 protocol")
}
if ps[1] != ProtocolWithName("udp") {
if ps[1].Code != ProtocolWithName("udp").Code {
t.Error(ps[1], ProtocolWithName("udp"))
t.Error("failed to get udp protocol")
}
}
func TestProtocolsWithString(t *testing.T) {
pwn := ProtocolWithName
good := map[string][]Protocol{
"/ip4": []Protocol{pwn("ip4")},
"/ip4/tcp": []Protocol{pwn("ip4"), pwn("tcp")},
"ip4/tcp/udp/ip6": []Protocol{pwn("ip4"), pwn("tcp"), pwn("udp"), pwn("ip6")},
"////////ip4/tcp": []Protocol{pwn("ip4"), pwn("tcp")},
"ip4/udp/////////": []Protocol{pwn("ip4"), pwn("udp")},
"////////ip4/tcp////////": []Protocol{pwn("ip4"), pwn("tcp")},
}
for s, ps1 := range good {
ps2, err := ProtocolsWithString(s)
if err != nil {
t.Error("ProtocolsWithString(%s) should have succeeded", s)
}
for i, ps1p := range ps1 {
ps2p := ps2[i]
if ps1p.Code != ps2p.Code {
t.Errorf("mismatch: %s != %s, %s", ps1p.Name, ps2p.Name, s)
}
}
}
bad := []string{
"dsijafd", // bogus proto
"/ip4/tcp/fidosafoidsa", // bogus proto
"////////ip4/tcp/21432141/////////", // bogus proto
"////////ip4///////tcp/////////", // empty protos in between
}
for _, s := range bad {
if _, err := ProtocolsWithString(s); err == nil {
t.Error("ProtocolsWithString(%s) should have failed", s)
}
}
}
func TestEncapsulate(t *testing.T) {
m, err := NewMultiaddr("/ip4/127.0.0.1/udp/1234")
if err != nil {

View File

@ -2,6 +2,8 @@ package multiaddr
import (
"encoding/binary"
"fmt"
"strings"
)
// Protocol is a Multiaddr protocol description structure.
@ -28,38 +30,57 @@ const (
)
// Protocols is the list of multiaddr protocols supported by this module.
var Protocols = []*Protocol{
&Protocol{P_IP4, 32, "ip4", CodeToVarint(P_IP4)},
&Protocol{P_TCP, 16, "tcp", CodeToVarint(P_TCP)},
&Protocol{P_UDP, 16, "udp", CodeToVarint(P_UDP)},
&Protocol{P_DCCP, 16, "dccp", CodeToVarint(P_DCCP)},
&Protocol{P_IP6, 128, "ip6", CodeToVarint(P_IP6)},
var Protocols = []Protocol{
Protocol{P_IP4, 32, "ip4", CodeToVarint(P_IP4)},
Protocol{P_TCP, 16, "tcp", CodeToVarint(P_TCP)},
Protocol{P_UDP, 16, "udp", CodeToVarint(P_UDP)},
Protocol{P_DCCP, 16, "dccp", CodeToVarint(P_DCCP)},
Protocol{P_IP6, 128, "ip6", CodeToVarint(P_IP6)},
// these require varint:
&Protocol{P_SCTP, 16, "sctp", CodeToVarint(P_SCTP)},
&Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP)},
&Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT)},
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"},
}
// ProtocolWithName returns the Protocol description with given string name.
func ProtocolWithName(s string) *Protocol {
func ProtocolWithName(s string) Protocol {
for _, p := range Protocols {
if p.Name == s {
return p
}
}
return nil
return Protocol{}
}
// ProtocolWithCode returns the Protocol description with given protocol code.
func ProtocolWithCode(c int) *Protocol {
func ProtocolWithCode(c int) Protocol {
for _, p := range Protocols {
if p.Code == c {
return p
}
}
return nil
return Protocol{}
}
// ProtocolsWithString returns a slice of protocols matching given string.
func ProtocolsWithString(s string) ([]Protocol, error) {
s = strings.Trim(s, "/")
sp := strings.Split(s, "/")
if len(sp) == 0 {
return nil, nil
}
t := make([]Protocol, len(sp))
for i, name := range sp {
p := ProtocolWithName(name)
if p.Code == 0 {
return nil, fmt.Errorf("no protocol with name: %s", name)
}
t[i] = p
}
return t, nil
}
// CodeToVarint converts an integer to a varint-encoded []byte

View File

@ -100,7 +100,7 @@ func MultiaddrProtocolsMatch(a, b ma.Multiaddr) bool {
}
for i, api := range ap {
if api != bp[i] {
if api.Code != bp[i].Code {
return false
}
}