mirror of
https://github.com/status-im/status-go.git
synced 2025-01-11 07:07:24 +00:00
183 lines
3.1 KiB
Go
183 lines
3.1 KiB
Go
|
package multiaddr
|
|||
|
|
|||
|
import (
|
|||
|
"bytes"
|
|||
|
"fmt"
|
|||
|
"strings"
|
|||
|
)
|
|||
|
|
|||
|
func stringToBytes(s string) ([]byte, error) {
|
|||
|
|
|||
|
// consume trailing slashes
|
|||
|
s = strings.TrimRight(s, "/")
|
|||
|
|
|||
|
b := new(bytes.Buffer)
|
|||
|
sp := strings.Split(s, "/")
|
|||
|
|
|||
|
if sp[0] != "" {
|
|||
|
return nil, fmt.Errorf("invalid multiaddr, must begin with /")
|
|||
|
}
|
|||
|
|
|||
|
// consume first empty elem
|
|||
|
sp = sp[1:]
|
|||
|
|
|||
|
for len(sp) > 0 {
|
|||
|
p := ProtocolWithName(sp[0])
|
|||
|
if p.Code == 0 {
|
|||
|
return nil, fmt.Errorf("no protocol with name %s", sp[0])
|
|||
|
}
|
|||
|
b.Write(CodeToVarint(p.Code))
|
|||
|
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)
|
|||
|
}
|
|||
|
|
|||
|
if p.Path {
|
|||
|
// it's a path protocol (terminal).
|
|||
|
// consume the rest of the address as the next component.
|
|||
|
sp = []string{"/" + strings.Join(sp, "/")}
|
|||
|
}
|
|||
|
|
|||
|
if p.Transcoder == nil {
|
|||
|
return nil, fmt.Errorf("no transcoder for %s protocol", p.Name)
|
|||
|
}
|
|||
|
a, err := p.Transcoder.StringToBytes(sp[0])
|
|||
|
if err != nil {
|
|||
|
return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err)
|
|||
|
}
|
|||
|
b.Write(a)
|
|||
|
sp = sp[1:]
|
|||
|
}
|
|||
|
|
|||
|
return b.Bytes(), nil
|
|||
|
}
|
|||
|
|
|||
|
func validateBytes(b []byte) (err error) {
|
|||
|
for len(b) > 0 {
|
|||
|
code, n, err := ReadVarintCode(b)
|
|||
|
if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
|
|||
|
b = b[n:]
|
|||
|
p := ProtocolWithCode(code)
|
|||
|
if p.Code == 0 {
|
|||
|
return fmt.Errorf("no protocol with code %d", code)
|
|||
|
}
|
|||
|
|
|||
|
if p.Size == 0 {
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
size, err := sizeForAddr(p, b)
|
|||
|
if err != nil {
|
|||
|
return err
|
|||
|
}
|
|||
|
|
|||
|
if len(b) < size || size < 0 {
|
|||
|
return fmt.Errorf("invalid value for size")
|
|||
|
}
|
|||
|
|
|||
|
b = b[size:]
|
|||
|
}
|
|||
|
|
|||
|
return nil
|
|||
|
}
|
|||
|
|
|||
|
func bytesToString(b []byte) (ret string, err error) {
|
|||
|
s := ""
|
|||
|
|
|||
|
for len(b) > 0 {
|
|||
|
code, n, err := ReadVarintCode(b)
|
|||
|
if err != nil {
|
|||
|
return "", err
|
|||
|
}
|
|||
|
|
|||
|
b = b[n:]
|
|||
|
p := ProtocolWithCode(code)
|
|||
|
if p.Code == 0 {
|
|||
|
return "", fmt.Errorf("no protocol with code %d", code)
|
|||
|
}
|
|||
|
s += "/" + p.Name
|
|||
|
|
|||
|
if p.Size == 0 {
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
size, err := sizeForAddr(p, b)
|
|||
|
if err != nil {
|
|||
|
return "", err
|
|||
|
}
|
|||
|
|
|||
|
if len(b) < size || size < 0 {
|
|||
|
return "", fmt.Errorf("invalid value for size")
|
|||
|
}
|
|||
|
|
|||
|
if p.Transcoder == nil {
|
|||
|
return "", fmt.Errorf("no transcoder for %s protocol", p.Name)
|
|||
|
}
|
|||
|
a, err := p.Transcoder.BytesToString(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, error) {
|
|||
|
switch {
|
|||
|
case p.Size > 0:
|
|||
|
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
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
func bytesSplit(b []byte) ([][]byte, error) {
|
|||
|
var ret [][]byte
|
|||
|
for len(b) > 0 {
|
|||
|
code, n, err := ReadVarintCode(b)
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
p := ProtocolWithCode(code)
|
|||
|
if p.Code == 0 {
|
|||
|
return nil, fmt.Errorf("no protocol with code %d", b[0])
|
|||
|
}
|
|||
|
|
|||
|
size, err := sizeForAddr(p, b[n:])
|
|||
|
if err != nil {
|
|||
|
return nil, err
|
|||
|
}
|
|||
|
|
|||
|
length := n + size
|
|||
|
ret = append(ret, b[:length])
|
|||
|
b = b[length:]
|
|||
|
}
|
|||
|
|
|||
|
return ret, nil
|
|||
|
}
|