mirror of
https://github.com/logos-messaging/go-multiaddr.git
synced 2026-01-02 13:03:11 +00:00
string <> []byte
This commit is contained in:
parent
ddfe13152f
commit
c5510ff4b8
74
README.md
Normal file
74
README.md
Normal file
@ -0,0 +1,74 @@
|
||||
# go-multiaddr
|
||||
|
||||
[multiaddr](https://github.com/jbenet/multiaddr) implementation in Go.
|
||||
|
||||
## Example
|
||||
|
||||
### Simple
|
||||
|
||||
```go
|
||||
import "github.com/jbenet/go-multiaddr"
|
||||
|
||||
m := multiaddr.NewString("/ip4/127.0.0.1/udp/1234")
|
||||
// <Multiaddr /ip4/127.0.0.1/udp/1234>
|
||||
m.buffer
|
||||
// <Buffer >
|
||||
m.String()
|
||||
// /ip4/127.0.0.1/udp/1234
|
||||
|
||||
// construct with Buffer
|
||||
m = multiaddr.Multiaddr{ Bytes: m.Bytes }
|
||||
// <Multiaddr /ip4/127.0.0.1/udp/1234>
|
||||
```
|
||||
|
||||
### Protocols
|
||||
|
||||
```go
|
||||
// get the multiaddr protocol codes
|
||||
m.ProtoCodes()
|
||||
// []int{4, 6}
|
||||
|
||||
// get the multiaddr protocol string codes
|
||||
m.ProtoNames()
|
||||
// []string{"ip4", "tcp"}
|
||||
|
||||
// get the multiaddr protocol description objects
|
||||
addr.Protos()
|
||||
// []Protocol{
|
||||
// Protocol{ Code: 4, Name: 'ip4', Size: 32},
|
||||
// Protocol{ Code: 17, Name: 'udp', Size: 16},
|
||||
// }
|
||||
```
|
||||
|
||||
### Other formats
|
||||
|
||||
```go
|
||||
// handles the stupid url version too
|
||||
m = multiaddr.NewUrl("udp4://127.0.0.1:1234")
|
||||
// <Multiaddr /ip4/127.0.0.1/udp/1234>
|
||||
m.Url(buf)
|
||||
// udp4://127.0.0.1:1234
|
||||
```
|
||||
|
||||
### En/decapsulate
|
||||
|
||||
```go
|
||||
m.Encapsulate(m.NewString("/sctp/5678"))
|
||||
// <Multiaddr /ip4/127.0.0.1/udp/1234/sctp/5678>
|
||||
m.Decapsulate(m.NewString("/udp")) // up to + inc last occurrence of subaddr
|
||||
// <Multiaddr /ip4/127.0.0.1>
|
||||
```
|
||||
|
||||
### Tunneling
|
||||
|
||||
Multiaddr allows expressing tunnels very nicely.
|
||||
|
||||
```js
|
||||
printer := multiaddr.NewString("/ip4/192.168.0.13/tcp/80")
|
||||
proxy := multiaddr.NewString("/ip4/10.20.30.40/tcp/443")
|
||||
printerOverProxy := proxy.Encapsulate(printer)
|
||||
// <Multiaddr /ip4/10.20.30.40/tcp/443/ip4/192.168.0.13/tcp/80>
|
||||
|
||||
proxyAgain := printerOverProxy.Decapsulate(multiaddr.NewString("/ip4"))
|
||||
// <Multiaddr /ip4/10.20.30.40/tcp/443>
|
||||
```
|
||||
50
codec.go
Normal file
50
codec.go
Normal file
@ -0,0 +1,50 @@
|
||||
package multiaddr
|
||||
|
||||
import(
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
||||
func StringToBytes(s string) ([]byte, error) {
|
||||
b := []byte{}
|
||||
sp := strings.Split(s, "/")
|
||||
|
||||
// consume first empty elem
|
||||
sp = sp[1:]
|
||||
|
||||
for ; len(sp) > 0 ; {
|
||||
p := ProtocolWithName(sp[0])
|
||||
if p == nil {
|
||||
return nil, fmt.Errorf("no protocol with name %s", sp[0])
|
||||
}
|
||||
b = append(b, byte(p.Code))
|
||||
|
||||
a := AddressStringToBytes(p, sp[1])
|
||||
b = append(b, a...)
|
||||
|
||||
sp = sp[2:]
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func BytesToString(b []byte) (string, error) {
|
||||
s := ""
|
||||
|
||||
for ; len(b) > 0 ; {
|
||||
p := ProtocolWithCode(int(b[0]))
|
||||
if p == nil {
|
||||
return "", fmt.Errorf("no protocol with code %d", b[0])
|
||||
}
|
||||
s = strings.Join([]string{s, "/", p.Name}, "")
|
||||
b = b[1:]
|
||||
|
||||
a := AddressBytesToString(p, b)
|
||||
if len(a) > 0 {
|
||||
s = strings.Join([]string{s, "/", a}, "")
|
||||
}
|
||||
b = b[(p.Size / 8):]
|
||||
}
|
||||
|
||||
return s, nil
|
||||
}
|
||||
43
convert.go
Normal file
43
convert.go
Normal file
@ -0,0 +1,43 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func AddressStringToBytes(p *Protocol, s string) []byte {
|
||||
switch p.Code {
|
||||
|
||||
// ipv4,6
|
||||
case 4, 41:
|
||||
return net.ParseIP(s).To4()
|
||||
|
||||
// tcp udp dccp sctp
|
||||
case 6, 17, 33, 132:
|
||||
b := make([]byte, 2)
|
||||
i, err := strconv.Atoi(s)
|
||||
if err == nil {
|
||||
binary.BigEndian.PutUint16(b, uint16(i))
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
return []byte{}
|
||||
}
|
||||
|
||||
func AddressBytesToString(p *Protocol, b []byte) string {
|
||||
switch p.Code {
|
||||
|
||||
// ipv4,6
|
||||
case 4, 41:
|
||||
return net.IP(b).String()
|
||||
|
||||
// tcp udp dccp sctp
|
||||
case 6, 17, 33, 132:
|
||||
i := binary.BigEndian.Uint16(b)
|
||||
return strconv.Itoa(int(i))
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
10
index.go
Normal file
10
index.go
Normal file
@ -0,0 +1,10 @@
|
||||
package multiaddr
|
||||
|
||||
type Multiaddr struct {
|
||||
Bytes []byte
|
||||
}
|
||||
|
||||
func NewString(s string) *Multiaddr {
|
||||
m := &Multiaddr{}
|
||||
return m
|
||||
}
|
||||
51
multiaddr_test.go
Normal file
51
multiaddr_test.go
Normal file
@ -0,0 +1,51 @@
|
||||
package multiaddr
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
"encoding/hex"
|
||||
)
|
||||
|
||||
|
||||
func TestStringToBytes(t *testing.T) {
|
||||
|
||||
testString := func(s string, h string) {
|
||||
b1, err := hex.DecodeString(h)
|
||||
if err != nil {
|
||||
t.Error("failed to decode hex", h)
|
||||
}
|
||||
|
||||
b2, err := StringToBytes(s)
|
||||
if err != nil {
|
||||
t.Error("failed to convert", s)
|
||||
}
|
||||
|
||||
if !bytes.Equal(b1, b2) {
|
||||
t.Error("failed to convert", s, "to", b1, "got", b2)
|
||||
}
|
||||
}
|
||||
|
||||
testString("/ip4/127.0.0.1/udp/1234", "047f0000011104d2")
|
||||
}
|
||||
|
||||
func TestBytesToString(t *testing.T) {
|
||||
|
||||
testString := func(s1 string, h string) {
|
||||
b, err := hex.DecodeString(h)
|
||||
if err != nil {
|
||||
t.Error("failed to decode hex", h)
|
||||
}
|
||||
|
||||
s2, err := BytesToString(b)
|
||||
if err != nil {
|
||||
t.Error("failed to convert", b)
|
||||
}
|
||||
|
||||
if s1 == s2 {
|
||||
t.Error("failed to convert", b, "to", s1, "got", s2)
|
||||
}
|
||||
}
|
||||
|
||||
testString("/ip4/127.0.0.1/udp/1234", "047f0000011104d2")
|
||||
}
|
||||
|
||||
42
protocols.go
Normal file
42
protocols.go
Normal file
@ -0,0 +1,42 @@
|
||||
package multiaddr
|
||||
|
||||
type Protocol struct {
|
||||
Code int
|
||||
Size int
|
||||
Name string
|
||||
}
|
||||
|
||||
// replicating table here to:
|
||||
// 1. avoid parsing the csv
|
||||
// 2. ensuring errors in the csv don't screw up code.
|
||||
// 3. changing a number has to happen in two places.
|
||||
|
||||
var Protocols = []Protocol{
|
||||
Protocol{4, 32, "ip4"},
|
||||
Protocol{6, 16, "tcp"},
|
||||
Protocol{17, 16, "udp"},
|
||||
Protocol{33, 16, "dccp"},
|
||||
Protocol{41, 128, "ip6"},
|
||||
// these require varint:
|
||||
Protocol{132, 16, "sctp"},
|
||||
// {480, 0, "http"},
|
||||
// {443, 0, "https"},
|
||||
}
|
||||
|
||||
func ProtocolWithName(s string) *Protocol {
|
||||
for _, p := range(Protocols) {
|
||||
if p.Name == s {
|
||||
return &p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ProtocolWithCode(c int) *Protocol {
|
||||
for _, p := range(Protocols) {
|
||||
if p.Code == c {
|
||||
return &p
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user