2014-07-03 23:42:24 -07:00
|
|
|
|
package multiaddr
|
|
|
|
|
|
2014-07-04 11:21:39 -07:00
|
|
|
|
import (
|
2016-05-04 12:11:09 -07:00
|
|
|
|
"bytes"
|
2014-07-04 11:21:39 -07:00
|
|
|
|
"fmt"
|
|
|
|
|
"strings"
|
2014-07-03 23:42:24 -07:00
|
|
|
|
)
|
|
|
|
|
|
2014-09-11 10:47:56 -07:00
|
|
|
|
func stringToBytes(s string) ([]byte, error) {
|
2014-10-10 20:40:51 -07:00
|
|
|
|
// consume trailing slashes
|
|
|
|
|
s = strings.TrimRight(s, "/")
|
|
|
|
|
|
2018-10-01 17:10:03 -07:00
|
|
|
|
var b bytes.Buffer
|
2014-07-04 11:21:39 -07:00
|
|
|
|
sp := strings.Split(s, "/")
|
2014-07-03 23:42:24 -07:00
|
|
|
|
|
2014-09-11 10:45:20 -07:00
|
|
|
|
if sp[0] != "" {
|
2019-05-16 18:37:21 -07:00
|
|
|
|
return nil, fmt.Errorf("failed to parse multiaddr %q: must begin with /", s)
|
2014-09-11 10:45:20 -07:00
|
|
|
|
}
|
|
|
|
|
|
2014-07-04 11:21:39 -07:00
|
|
|
|
// consume first empty elem
|
|
|
|
|
sp = sp[1:]
|
2014-07-03 23:42:24 -07:00
|
|
|
|
|
2014-07-04 11:21:39 -07:00
|
|
|
|
for len(sp) > 0 {
|
2018-12-14 19:37:13 +11:00
|
|
|
|
name := sp[0]
|
|
|
|
|
p := ProtocolWithName(name)
|
2015-01-09 05:37:02 -08:00
|
|
|
|
if p.Code == 0 {
|
2019-05-16 18:37:21 -07:00
|
|
|
|
return nil, fmt.Errorf("failed to parse multiaddr %q: unknown protocol %s", s, sp[0])
|
2014-07-04 11:21:39 -07:00
|
|
|
|
}
|
2018-06-22 14:31:41 -07:00
|
|
|
|
_, _ = b.Write(CodeToVarint(p.Code))
|
2014-11-19 13:01:52 -08:00
|
|
|
|
sp = sp[1:]
|
2014-07-03 23:42:24 -07:00
|
|
|
|
|
2015-01-17 21:12:54 -08:00
|
|
|
|
if p.Size == 0 { // no length.
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(sp) < 1 {
|
2019-05-16 18:37:21 -07:00
|
|
|
|
return nil, fmt.Errorf("failed to parse multiaddr %q: unexpected end of multiaddr", s)
|
2015-01-17 21:12:54 -08:00
|
|
|
|
}
|
2016-05-04 12:11:09 -07:00
|
|
|
|
|
2016-09-12 02:03:41 -04:00
|
|
|
|
if p.Path {
|
|
|
|
|
// it's a path protocol (terminal).
|
|
|
|
|
// consume the rest of the address as the next component.
|
|
|
|
|
sp = []string{"/" + strings.Join(sp, "/")}
|
|
|
|
|
}
|
|
|
|
|
|
2016-10-14 11:48:19 -04:00
|
|
|
|
a, err := p.Transcoder.StringToBytes(sp[0])
|
2015-01-17 21:12:54 -08:00
|
|
|
|
if err != nil {
|
2019-05-16 18:37:21 -07:00
|
|
|
|
return nil, fmt.Errorf("failed to parse multiaddr %q: invalid value %q for protocol %s: %s", s, sp[0], p.Name, err)
|
2014-11-19 13:01:52 -08:00
|
|
|
|
}
|
2018-06-18 12:23:33 -07:00
|
|
|
|
if p.Size < 0 { // varint size.
|
2018-06-22 14:31:41 -07:00
|
|
|
|
_, _ = b.Write(CodeToVarint(len(a)))
|
2018-06-18 12:23:33 -07:00
|
|
|
|
}
|
2016-05-04 12:11:09 -07:00
|
|
|
|
b.Write(a)
|
2015-01-17 21:12:54 -08:00
|
|
|
|
sp = sp[1:]
|
2014-07-04 11:21:39 -07:00
|
|
|
|
}
|
2016-05-04 12:11:09 -07:00
|
|
|
|
|
|
|
|
|
return b.Bytes(), nil
|
2014-07-03 23:42:24 -07:00
|
|
|
|
}
|
|
|
|
|
|
2016-04-29 14:16:41 -07:00
|
|
|
|
func validateBytes(b []byte) (err error) {
|
|
|
|
|
for len(b) > 0 {
|
|
|
|
|
code, n, err := ReadVarintCode(b)
|
2016-05-04 13:26:50 -07:00
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-29 14:16:41 -07:00
|
|
|
|
b = b[n:]
|
|
|
|
|
p := ProtocolWithCode(code)
|
|
|
|
|
if p.Code == 0 {
|
|
|
|
|
return fmt.Errorf("no protocol with code %d", code)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if p.Size == 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2014-07-04 11:21:39 -07:00
|
|
|
|
|
2018-06-18 12:23:33 -07:00
|
|
|
|
n, size, err := sizeForAddr(p, b)
|
2016-04-29 14:16:41 -07:00
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-18 12:23:33 -07:00
|
|
|
|
b = b[n:]
|
|
|
|
|
|
2016-05-04 10:51:57 -07:00
|
|
|
|
if len(b) < size || size < 0 {
|
2018-11-25 15:27:50 -05:00
|
|
|
|
return fmt.Errorf("invalid value for size %d", len(b))
|
2016-04-29 14:16:41 -07:00
|
|
|
|
}
|
2016-05-04 10:51:57 -07:00
|
|
|
|
|
2018-06-18 19:42:26 -07:00
|
|
|
|
err = p.Transcoder.ValidateBytes(b[:size])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-29 14:16:41 -07:00
|
|
|
|
b = b[size:]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
2016-05-04 13:26:50 -07:00
|
|
|
|
|
2018-10-01 15:51:41 -07:00
|
|
|
|
func readComponent(b []byte) (int, Component, error) {
|
|
|
|
|
var offset int
|
|
|
|
|
code, n, err := ReadVarintCode(b)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, Component{}, err
|
|
|
|
|
}
|
|
|
|
|
offset += n
|
2014-07-04 11:21:39 -07:00
|
|
|
|
|
2018-10-01 15:51:41 -07:00
|
|
|
|
p := ProtocolWithCode(code)
|
|
|
|
|
if p.Code == 0 {
|
|
|
|
|
return 0, Component{}, fmt.Errorf("no protocol with code %d", code)
|
|
|
|
|
}
|
2014-11-19 13:01:52 -08:00
|
|
|
|
|
2018-10-01 15:51:41 -07:00
|
|
|
|
if p.Size == 0 {
|
|
|
|
|
return offset, Component{
|
|
|
|
|
bytes: b[:offset],
|
|
|
|
|
offset: offset,
|
|
|
|
|
protocol: p,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
2014-07-04 11:21:39 -07:00
|
|
|
|
|
2018-10-01 15:51:41 -07:00
|
|
|
|
n, size, err := sizeForAddr(p, b[offset:])
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, Component{}, err
|
|
|
|
|
}
|
2015-01-17 21:12:54 -08:00
|
|
|
|
|
2018-10-01 15:51:41 -07:00
|
|
|
|
offset += n
|
2016-04-29 14:16:41 -07:00
|
|
|
|
|
2018-10-01 15:51:41 -07:00
|
|
|
|
if len(b[offset:]) < size || size < 0 {
|
2018-11-25 15:27:50 -05:00
|
|
|
|
return 0, Component{}, fmt.Errorf("invalid value for size %d", len(b[offset:]))
|
2018-10-01 15:51:41 -07:00
|
|
|
|
}
|
2018-06-18 12:23:33 -07:00
|
|
|
|
|
2018-10-01 15:51:41 -07:00
|
|
|
|
return offset + size, Component{
|
|
|
|
|
bytes: b[:offset+size],
|
|
|
|
|
protocol: p,
|
|
|
|
|
offset: offset,
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
2016-05-04 12:11:09 -07:00
|
|
|
|
|
2018-10-01 15:51:41 -07:00
|
|
|
|
func bytesToString(b []byte) (ret string, err error) {
|
|
|
|
|
var buf strings.Builder
|
|
|
|
|
|
|
|
|
|
for len(b) > 0 {
|
|
|
|
|
n, c, err := readComponent(b)
|
2015-01-17 21:12:54 -08:00
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
2018-10-01 15:51:41 -07:00
|
|
|
|
b = b[n:]
|
|
|
|
|
c.writeTo(&buf)
|
2014-07-04 11:21:39 -07:00
|
|
|
|
}
|
|
|
|
|
|
2018-10-01 15:51:41 -07:00
|
|
|
|
return buf.String(), nil
|
2014-07-03 23:42:24 -07:00
|
|
|
|
}
|
2014-07-03 23:44:09 -07:00
|
|
|
|
|
2018-06-18 12:23:33 -07:00
|
|
|
|
func sizeForAddr(p Protocol, b []byte) (skip, size int, err error) {
|
2015-01-20 13:54:05 -08:00
|
|
|
|
switch {
|
|
|
|
|
case p.Size > 0:
|
2018-06-18 12:23:33 -07:00
|
|
|
|
return 0, (p.Size / 8), nil
|
2015-01-20 13:54:05 -08:00
|
|
|
|
case p.Size == 0:
|
2018-06-18 12:23:33 -07:00
|
|
|
|
return 0, 0, nil
|
2015-01-20 13:54:05 -08:00
|
|
|
|
default:
|
2016-04-29 14:16:41 -07:00
|
|
|
|
size, n, err := ReadVarintCode(b)
|
|
|
|
|
if err != nil {
|
2018-06-18 12:23:33 -07:00
|
|
|
|
return 0, 0, err
|
2016-04-29 14:16:41 -07:00
|
|
|
|
}
|
2018-06-18 12:23:33 -07:00
|
|
|
|
return n, size, nil
|
2015-01-20 13:54:05 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-29 14:16:41 -07:00
|
|
|
|
func bytesSplit(b []byte) ([][]byte, error) {
|
|
|
|
|
var ret [][]byte
|
|
|
|
|
for len(b) > 0 {
|
|
|
|
|
code, n, err := ReadVarintCode(b)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
2014-11-04 23:20:17 -08:00
|
|
|
|
}
|
|
|
|
|
|
2014-11-19 13:01:52 -08:00
|
|
|
|
p := ProtocolWithCode(code)
|
2015-01-09 05:37:02 -08:00
|
|
|
|
if p.Code == 0 {
|
2016-04-29 14:16:41 -07:00
|
|
|
|
return nil, fmt.Errorf("no protocol with code %d", b[0])
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-18 12:23:33 -07:00
|
|
|
|
n2, size, err := sizeForAddr(p, b[n:])
|
2016-04-29 14:16:41 -07:00
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
2014-11-04 23:20:17 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-18 12:23:33 -07:00
|
|
|
|
length := n + n2 + size
|
2014-11-04 23:20:17 -08:00
|
|
|
|
ret = append(ret, b[:length])
|
|
|
|
|
b = b[length:]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
|
}
|