Skip to content

Commit

Permalink
util/ipfsaddr: Multiaddr() + ID()
Browse files Browse the repository at this point in the history
  • Loading branch information
jbenet committed Jan 20, 2015
1 parent fd041ec commit 4f2c313
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 0 deletions.
80 changes: 80 additions & 0 deletions util/ipfsaddr/ipfsaddr.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package ipfsaddr

import (
"errors"
"strings"

ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"

peer "github.com/jbenet/go-ipfs/p2p/peer"
)

// ErrInvalidAddr signals an address is not a valid ipfs address.
var ErrInvalidAddr = errors.New("invalid ipfs address")

type IPFSAddr interface {
ID() peer.ID
Multiaddr() ma.Multiaddr
}

type ipfsAddr struct {
ma ma.Multiaddr
id peer.ID
}

func (a ipfsAddr) ID() peer.ID {
return a.id
}

func (a ipfsAddr) Multiaddr() ma.Multiaddr {
return a.ma
}

// ParseString parses a string representation of an address into an IPFSAddr
func ParseString(str string) (a IPFSAddr, err error) {
if str == "" {
return nil, ErrInvalidAddr
}

m, err := ma.NewMultiaddr(str)
if err != nil {
return nil, err
}

return ParseMultiaddr(m)
}

// ParseMultiaddr parses a multiaddr into an IPFSAddr
func ParseMultiaddr(m ma.Multiaddr) (a IPFSAddr, err error) {
// // never panic.
// defer func() {
// if r := recover(); r != nil {
// a = nil
// err = ErrInvalidAddr
// }
// }()

if m == nil {
return nil, ErrInvalidAddr
}

// make sure it's an ipfs addr
parts := ma.Split(m)
if len(parts) < 1 {
return nil, ErrInvalidAddr
}
ipfspart := parts[len(parts)-1] // last part
if ipfspart.Protocols()[0].Code != ma.P_IPFS {
return nil, ErrInvalidAddr
}

// make sure ipfs id parses as a peer.ID
peerIdParts := strings.Split(ipfspart.String(), "/")
peerIdStr := peerIdParts[len(peerIdParts)-1]
id, err := peer.IDB58Decode(peerIdStr)
if err != nil {
return nil, err
}

return ipfsAddr{ma: m, id: id}, nil
}
117 changes: 117 additions & 0 deletions util/ipfsaddr/ipfsaddr_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package ipfsaddr

import (
"strings"
"testing"

ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
peer "github.com/jbenet/go-ipfs/p2p/peer"
)

var good = []string{
"/ipfs/5dru6bJPUM1B7N69528u49DJiWZnok",
"/ipfs/kTRX47RthhwNzWdi6ggwqjuX",
"/ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR",
"/ip4/1.2.3.4/tcp/1234/ipfs/5dru6bJPUM1B7N69528u49DJiWZnok",
"/ip4/1.2.3.4/tcp/1234/ipfs/kTRX47RthhwNzWdi6ggwqjuX",
"/ip4/1.2.3.4/tcp/1234/ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR",
}

var bad = []string{
"5dru6bJPUM1B7N69528u49DJiWZnok", // bad ma
"kTRX47RthhwNzWdi6ggwqjuX", // bad ma
"QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR", // bad ma
"ipfs/5dru6bJPUM1B7N69528u49DJiWZnok", // bad ma
"ipfs/kTRX47RthhwNzWdi6ggwqjuX", // bad ma
"ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR", // bad ma
"/ipfs/5dru6bJPUM1B7N69528u49DJiWZno", // bad mh
"/ipfs/kTRX47RthhwNzWdi6ggwqju", // bad mh
"/ipfs/QmUCseQWXCSrhf9edzVKTvj8o8Ts5aXFGNPameZRPJ6uR", // bad mh
"/ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR/tcp/1234", // ipfs not last
"/ip4/1.2.3.4/tcp/ipfs/5dru6bJPUM1B7N69528u49DJiWZnok", // bad tcp part
"/ip4/tcp/1234/ipfs/kTRX47RthhwNzWdi6ggwqjuX", // bad ip part
"/ip4/1.2.3.4/tcp/1234/ipfs", // no id
"/ip4/1.2.3.4/tcp/1234/ipfs/", // no id
}

func newMultiaddr(t *testing.T, s string) ma.Multiaddr {
maddr, err := ma.NewMultiaddr(s)
if err != nil {
t.Fatal(err)
}
return maddr
}

func TestParseStringGood(t *testing.T) {
for _, g := range good {
if _, err := ParseString(g); err != nil {
t.Error("failed to parse", g, err)
}
}
}

func TestParseStringBad(t *testing.T) {
for _, b := range bad {
if _, err := ParseString(b); err == nil {
t.Error("succeeded in parsing", b)
}
}
}

func TestParseMultiaddrGood(t *testing.T) {
for _, g := range good {
if _, err := ParseMultiaddr(newMultiaddr(t, g)); err != nil {
t.Error("failed to parse", g, err)
}
}
}

func TestParseMultiaddrBad(t *testing.T) {
for _, b := range bad {
m, err := ma.NewMultiaddr(b)
if err != nil {
continue // skip these.
}

if _, err := ParseMultiaddr(m); err == nil {
t.Error("succeeded in parsing", m)
}
}
}

func TestIDMatches(t *testing.T) {
for _, g := range good {
a, err := ParseString(g)
if err != nil {
t.Error("failed to parse", g, err)
continue
}

sp := strings.Split(g, "/")
sid := sp[len(sp)-1]
id, err := peer.IDB58Decode(sid)
if err != nil {
t.Error("failed to parse", sid, err)
continue
}

if a.ID() != id {
t.Error("not equal", a.ID(), id)
}
}
}

func TestMultiaddrMatches(t *testing.T) {
for _, g := range good {
a, err := ParseString(g)
if err != nil {
t.Error("failed to parse", g, err)
continue
}

m := newMultiaddr(t, g)
if !a.Multiaddr().Equal(m) {
t.Error("not equal", a.Multiaddr(), m)
}
}
}

0 comments on commit 4f2c313

Please sign in to comment.