Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions codec.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"net"
"strconv"
"strings"
"errors"

mh "github.com/jbenet/go-multihash"
)
Expand Down Expand Up @@ -43,6 +44,12 @@ func stringToBytes(s string) ([]byte, error) {
return nil, fmt.Errorf("protocol requires address, none given: %s", p.Name)
}

if p.Path {
// it's a path protocol (terminal).
// consume the rest of the address as the next component.
sp = []string{"/" + strings.Join(sp, "/")}
}

a, err := addressStringToBytes(p, sp[0])
if err != nil {
return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err)
Expand Down Expand Up @@ -134,12 +141,17 @@ func sizeForAddr(p Protocol, b []byte) (int, error) {
return (p.Size / 8), nil
case p.Size == 0:
return 0, nil
case p.Path:
size, n, err := ReadVarintCode(b)
if err != nil {
return 0, err
}
return size + n, nil
default:
size, n, err := ReadVarintCode(b)
if err != nil {
return 0, err
}

return size + n, nil
}
}
Expand Down Expand Up @@ -243,6 +255,12 @@ func addressStringToBytes(p Protocol, s string) ([]byte, error) {
size := CodeToVarint(len(m))
b := append(size, m...)
return b, nil

case P_UNIX:
// the address is the whole remaining string, prefixed by a varint len
size := CodeToVarint(len(s))
b := append(size, []byte(s)...)
return b, nil
}

return []byte{}, fmt.Errorf("failed to parse %s addr: unknown", p.Name)
Expand All @@ -269,7 +287,7 @@ func addressBytesToString(p Protocol, b []byte) (string, error) {

b = b[n:]
if len(b) != size {
return "", fmt.Errorf("inconsistent lengths")
return "", errors.New("inconsistent lengths")
}
m, err := mh.Cast(b)
if err != nil {
Expand All @@ -282,7 +300,25 @@ func addressBytesToString(p Protocol, b []byte) (string, error) {
port := binary.BigEndian.Uint16(b[10:12])
return addr + ":"+ strconv.Itoa(int(port)), nil

case P_UNIX:
// the address is a varint len prefixed string
size, n, err := ReadVarintCode(b)
if err != nil {
return "", err
}

b = b[n:]
if len(b) != size {
return "", errors.New("inconsistent lengths")
}
if size == 0 {
return "", errors.New("invalid length")
}
s := string(b)
s = s[1:] // remove starting slash
return s, nil

default:
return "", fmt.Errorf("unknown protocol")
return "", errors.New("unknown protocol")
}
}
2 changes: 1 addition & 1 deletion multiaddr.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ func (m *multiaddr) ValueForProtocol(code int) (string, error) {
if p.Size == 0 {
return "", nil
}
return strings.Split(sub.String(), "/")[2], nil
return strings.SplitN(sub.String(), "/", 3)[2], nil
}
}

Expand Down
10 changes: 10 additions & 0 deletions multiaddr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ func TestConstructFails(t *testing.T) {
"/ip4/127.0.0.1/tcp",
"/ip4/127.0.0.1/ipfs",
"/ip4/127.0.0.1/ipfs/tcp",
"/unix",
"/ip4/1.2.3.4/tcp/80/unix",
}

for _, a := range cases {
Expand Down Expand Up @@ -81,6 +83,10 @@ func TestConstructSucceeds(t *testing.T) {
"/ip4/127.0.0.1/tcp/1234/",
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
"/unix/a/b/c/d/e",
"/unix/stdio",
"/ip4/1.2.3.4/tcp/80/unix/a/b/c/d/e/f",
"/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234/unix/stdio",
}

for _, a := range cases {
Expand Down Expand Up @@ -353,6 +359,10 @@ func TestGetValue(t *testing.T) {
assertValueForProto(t, a, P_IP4, "0.0.0.0")
assertValueForProto(t, a, P_UDP, "12345")
assertValueForProto(t, a, P_UTP, "")

a = newMultiaddr(t, "/ip4/0.0.0.0/unix/a/b/c/d") // ending in a path one.
assertValueForProto(t, a, P_IP4, "0.0.0.0")
assertValueForProto(t, a, P_UNIX, "a/b/c/d")
}

func TestFuzzBytes(t *testing.T) {
Expand Down
2 changes: 2 additions & 0 deletions protocols.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
code size name

4 32 ip4
6 16 tcp
17 16 udp
Expand All @@ -7,6 +8,7 @@ code size name
132 16 sctp
301 0 utp
302 0 udt
400 V unix
421 V ipfs
480 0 http
443 0 https
Expand Down
27 changes: 15 additions & 12 deletions protocols.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Protocol struct {
Size int // a size of -1 indicates a length-prefixed variable size
Name string
VCode []byte
Path bool // indicates a path protocol (eg unix, http)
}

// replicating table here to:
Expand All @@ -27,6 +28,7 @@ const (
P_SCTP = 132
P_UTP = 301
P_UDT = 302
P_UNIX = 400
P_IPFS = 421
P_HTTP = 480
P_HTTPS = 443
Expand All @@ -40,19 +42,20 @@ 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)},
Protocol{P_IP4, 32, "ip4", CodeToVarint(P_IP4), false},
Protocol{P_TCP, 16, "tcp", CodeToVarint(P_TCP), false},
Protocol{P_UDP, 16, "udp", CodeToVarint(P_UDP), false},
Protocol{P_DCCP, 16, "dccp", CodeToVarint(P_DCCP), false},
Protocol{P_IP6, 128, "ip6", CodeToVarint(P_IP6), false},
// these require varint:
Protocol{P_SCTP, 16, "sctp", CodeToVarint(P_SCTP)},
Protocol{P_ONION, 96, "onion", CodeToVarint(P_ONION)},
Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP)},
Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT)},
Protocol{P_HTTP, 0, "http", CodeToVarint(P_HTTP)},
Protocol{P_HTTPS, 0, "https", CodeToVarint(P_HTTPS)},
Protocol{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS)},
Protocol{P_SCTP, 16, "sctp", CodeToVarint(P_SCTP), false},
Protocol{P_ONION, 96, "onion", CodeToVarint(P_ONION), false},
Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP), false},
Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT), false},
Protocol{P_HTTP, 0, "http", CodeToVarint(P_HTTP), false},
Protocol{P_HTTPS, 0, "https", CodeToVarint(P_HTTPS), false},
Protocol{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS), false},
Protocol{P_UNIX, LengthPrefixedVarSize, "unix", CodeToVarint(P_UNIX), true},
}

func AddProtocol(p Protocol) error {
Expand Down