diff --git a/README.md b/README.md index 8a40027..b63ffa2 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ ```go import "github.com/jbenet/go-multiaddr" -m := multiaddr.NewString("/ip4/127.0.0.1/udp/1234") +m := multiaddr.NewMultiaddr("/ip4/127.0.0.1/udp/1234") // m.buffer // @@ -45,9 +45,9 @@ m.Url(buf) ### En/decapsulate ```go -m.Encapsulate(m.NewString("/sctp/5678")) +m.Encapsulate(m.NewMultiaddr("/sctp/5678")) // -m.Decapsulate(m.NewString("/udp")) // up to + inc last occurrence of subaddr +m.Decapsulate(m.NewMultiaddr("/udp")) // up to + inc last occurrence of subaddr // ``` @@ -56,11 +56,11 @@ m.Decapsulate(m.NewString("/udp")) // up to + inc last occurrence of subaddr 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") +printer := multiaddr.NewMultiaddr("/ip4/192.168.0.13/tcp/80") +proxy := multiaddr.NewMultiaddr("/ip4/10.20.30.40/tcp/443") printerOverProxy := proxy.Encapsulate(printer) // -proxyAgain := printerOverProxy.Decapsulate(multiaddr.NewString("/ip4")) +proxyAgain := printerOverProxy.Decapsulate(multiaddr.NewMultiaddr("/ip4")) // ``` diff --git a/codec.go b/codec.go index 3e056a9..93bee7c 100644 --- a/codec.go +++ b/codec.go @@ -50,7 +50,7 @@ func BytesToString(b []byte) (ret string, err error) { s = strings.Join([]string{s, "/", p.Name}, "") b = b[1:] - a := AddressBytesToString(p, b) + a := AddressBytesToString(p, b[:(p.Size / 8)]) if len(a) > 0 { s = strings.Join([]string{s, "/", a}, "") } diff --git a/index.go b/index.go index ec0e054..6e54fb5 100644 --- a/index.go +++ b/index.go @@ -2,13 +2,14 @@ package multiaddr import ( "fmt" + "strings" ) type Multiaddr struct { Bytes []byte } -func NewString(s string) (*Multiaddr, error) { +func NewMultiaddr(s string) (*Multiaddr, error) { b, err := StringToBytes(s) if err != nil { return nil, err @@ -42,3 +43,27 @@ func (m *Multiaddr) Protocols() (ret []*Protocol, err error) { } return ps, nil } + +func (m *Multiaddr) Encapsulate(o *Multiaddr) *Multiaddr { + b := make([]byte, len(m.Bytes) + len(o.Bytes)) + b = append(m.Bytes, o.Bytes...) + return &Multiaddr{Bytes: b} +} + +func (m *Multiaddr) Decapsulate(o *Multiaddr) (*Multiaddr, error) { + s1, err := m.String() + if err != nil { + return nil, err + } + + s2, err := o.String() + if err != nil { + return nil, err + } + + i := strings.LastIndex(s1, s2) + if i < 0 { + return nil, fmt.Errorf("%s not contained in %s", s2, s1) + } + return NewMultiaddr(s1[:i]) +} diff --git a/multiaddr_test.go b/multiaddr_test.go index 60deda4..777ced8 100644 --- a/multiaddr_test.go +++ b/multiaddr_test.go @@ -41,7 +41,7 @@ func TestBytesToString(t *testing.T) { t.Error("failed to convert", b) } - if s1 == s2 { + if s1 != s2 { t.Error("failed to convert", b, "to", s1, "got", s2) } } @@ -51,7 +51,7 @@ func TestBytesToString(t *testing.T) { func TestProtocols(t *testing.T) { - m, err := NewString("/ip4/127.0.0.1/udp/1234") + m, err := NewMultiaddr("/ip4/127.0.0.1/udp/1234") if err != nil { t.Error("failed to construct", "/ip4/127.0.0.1/udp/1234") } @@ -72,3 +72,40 @@ func TestProtocols(t *testing.T) { } } + +func TestEncapsulate(t *testing.T) { + m, err := NewMultiaddr("/ip4/127.0.0.1/udp/1234") + if err != nil { + t.Error(err) + } + + m2, err := NewMultiaddr("/udp/5678") + if err != nil { + t.Error(err) + } + + b := m.Encapsulate(m2) + if s, _ := b.String(); s != "/ip4/127.0.0.1/udp/1234/udp/5678" { + t.Error("encapsulate /ip4/127.0.0.1/udp/1234/udp/5678 failed.", s) + } + + m3, _ := NewMultiaddr("/udp/5678") + c, err := b.Decapsulate(m3) + if err != nil { + t.Error("decapsulate /udp failed.", err) + } + + if s, _ := c.String(); s != "/ip4/127.0.0.1/udp/1234" { + t.Error("decapsulate /udp failed.", "/ip4/127.0.0.1/udp/1234", s) + } + + m4, _ := NewMultiaddr("/ip4/127.0.0.1") + d, err := c.Decapsulate(m4) + if err != nil { + t.Error("decapsulate /ip4 failed.", err) + } + + if s, _ := d.String(); s != "" { + t.Error("decapsulate /ip4 failed.", "/", s) + } +}