@cryptotaxi247 / kubo / commits / 2e6be0b19

util/ipfsaddr: Multiaddr() + ID()

Juan Batiz-Benet committed Jan 20, 2015 at 14:22 UTC 2e6be0b1997820a6255de59173ce669f31a2de9f
2 files changed +197
util/ipfsaddr/ipfsaddr.go new
+80
@@ -0,0 +1,80 @@
1 +package ipfsaddr
2 +
3 +import (
4 + "errors"
5 + "strings"
6 +
7 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8 +
9 + peer "github.com/jbenet/go-ipfs/p2p/peer"
10 +)
11 +
12 +// ErrInvalidAddr signals an address is not a valid ipfs address.
13 +var ErrInvalidAddr = errors.New("invalid ipfs address")
14 +
15 +type IPFSAddr interface {
16 + ID() peer.ID
17 + Multiaddr() ma.Multiaddr
18 +}
19 +
20 +type ipfsAddr struct {
21 + ma ma.Multiaddr
22 + id peer.ID
23 +}
24 +
25 +func (a ipfsAddr) ID() peer.ID {
26 + return a.id
27 +}
28 +
29 +func (a ipfsAddr) Multiaddr() ma.Multiaddr {
30 + return a.ma
31 +}
32 +
33 +// ParseString parses a string representation of an address into an IPFSAddr
34 +func ParseString(str string) (a IPFSAddr, err error) {
35 + if str == "" {
36 + return nil, ErrInvalidAddr
37 + }
38 +
39 + m, err := ma.NewMultiaddr(str)
40 + if err != nil {
41 + return nil, err
42 + }
43 +
44 + return ParseMultiaddr(m)
45 +}
46 +
47 +// ParseMultiaddr parses a multiaddr into an IPFSAddr
48 +func ParseMultiaddr(m ma.Multiaddr) (a IPFSAddr, err error) {
49 + // // never panic.
50 + // defer func() {
51 + // if r := recover(); r != nil {
52 + // a = nil
53 + // err = ErrInvalidAddr
54 + // }
55 + // }()
56 +
57 + if m == nil {
58 + return nil, ErrInvalidAddr
59 + }
60 +
61 + // make sure it's an ipfs addr
62 + parts := ma.Split(m)
63 + if len(parts) < 1 {
64 + return nil, ErrInvalidAddr
65 + }
66 + ipfspart := parts[len(parts)-1] // last part
67 + if ipfspart.Protocols()[0].Code != ma.P_IPFS {
68 + return nil, ErrInvalidAddr
69 + }
70 +
71 + // make sure ipfs id parses as a peer.ID
72 + peerIdParts := strings.Split(ipfspart.String(), "/")
73 + peerIdStr := peerIdParts[len(peerIdParts)-1]
74 + id, err := peer.IDB58Decode(peerIdStr)
75 + if err != nil {
76 + return nil, err
77 + }
78 +
79 + return ipfsAddr{ma: m, id: id}, nil
80 +}
util/ipfsaddr/ipfsaddr_test.go new
+117
@@ -0,0 +1,117 @@
1 +package ipfsaddr
2 +
3 +import (
4 + "strings"
5 + "testing"
6 +
7 + ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
8 + peer "github.com/jbenet/go-ipfs/p2p/peer"
9 +)
10 +
11 +var good = []string{
12 + "/ipfs/5dru6bJPUM1B7N69528u49DJiWZnok",
13 + "/ipfs/kTRX47RthhwNzWdi6ggwqjuX",
14 + "/ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR",
15 + "/ip4/1.2.3.4/tcp/1234/ipfs/5dru6bJPUM1B7N69528u49DJiWZnok",
16 + "/ip4/1.2.3.4/tcp/1234/ipfs/kTRX47RthhwNzWdi6ggwqjuX",
17 + "/ip4/1.2.3.4/tcp/1234/ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR",
18 +}
19 +
20 +var bad = []string{
21 + "5dru6bJPUM1B7N69528u49DJiWZnok", // bad ma
22 + "kTRX47RthhwNzWdi6ggwqjuX", // bad ma
23 + "QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR", // bad ma
24 + "ipfs/5dru6bJPUM1B7N69528u49DJiWZnok", // bad ma
25 + "ipfs/kTRX47RthhwNzWdi6ggwqjuX", // bad ma
26 + "ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR", // bad ma
27 + "/ipfs/5dru6bJPUM1B7N69528u49DJiWZno", // bad mh
28 + "/ipfs/kTRX47RthhwNzWdi6ggwqju", // bad mh
29 + "/ipfs/QmUCseQWXCSrhf9edzVKTvj8o8Ts5aXFGNPameZRPJ6uR", // bad mh
30 + "/ipfs/QmUCseQWXCSrhf9edzVKTvoj8o8Ts5aXFGNPameZRPJ6uR/tcp/1234", // ipfs not last
31 + "/ip4/1.2.3.4/tcp/ipfs/5dru6bJPUM1B7N69528u49DJiWZnok", // bad tcp part
32 + "/ip4/tcp/1234/ipfs/kTRX47RthhwNzWdi6ggwqjuX", // bad ip part
33 + "/ip4/1.2.3.4/tcp/1234/ipfs", // no id
34 + "/ip4/1.2.3.4/tcp/1234/ipfs/", // no id
35 +}
36 +
37 +func newMultiaddr(t *testing.T, s string) ma.Multiaddr {
38 + maddr, err := ma.NewMultiaddr(s)
39 + if err != nil {
40 + t.Fatal(err)
41 + }
42 + return maddr
43 +}
44 +
45 +func TestParseStringGood(t *testing.T) {
46 + for _, g := range good {
47 + if _, err := ParseString(g); err != nil {
48 + t.Error("failed to parse", g, err)
49 + }
50 + }
51 +}
52 +
53 +func TestParseStringBad(t *testing.T) {
54 + for _, b := range bad {
55 + if _, err := ParseString(b); err == nil {
56 + t.Error("succeeded in parsing", b)
57 + }
58 + }
59 +}
60 +
61 +func TestParseMultiaddrGood(t *testing.T) {
62 + for _, g := range good {
63 + if _, err := ParseMultiaddr(newMultiaddr(t, g)); err != nil {
64 + t.Error("failed to parse", g, err)
65 + }
66 + }
67 +}
68 +
69 +func TestParseMultiaddrBad(t *testing.T) {
70 + for _, b := range bad {
71 + m, err := ma.NewMultiaddr(b)
72 + if err != nil {
73 + continue // skip these.
74 + }
75 +
76 + if _, err := ParseMultiaddr(m); err == nil {
77 + t.Error("succeeded in parsing", m)
78 + }
79 + }
80 +}
81 +
82 +func TestIDMatches(t *testing.T) {
83 + for _, g := range good {
84 + a, err := ParseString(g)
85 + if err != nil {
86 + t.Error("failed to parse", g, err)
87 + continue
88 + }
89 +
90 + sp := strings.Split(g, "/")
91 + sid := sp[len(sp)-1]
92 + id, err := peer.IDB58Decode(sid)
93 + if err != nil {
94 + t.Error("failed to parse", sid, err)
95 + continue
96 + }
97 +
98 + if a.ID() != id {
99 + t.Error("not equal", a.ID(), id)
100 + }
101 + }
102 +}
103 +
104 +func TestMultiaddrMatches(t *testing.T) {
105 + for _, g := range good {
106 + a, err := ParseString(g)
107 + if err != nil {
108 + t.Error("failed to parse", g, err)
109 + continue
110 + }
111 +
112 + m := newMultiaddr(t, g)
113 + if !a.Multiaddr().Equal(m) {
114 + t.Error("not equal", a.Multiaddr(), m)
115 + }
116 + }
117 +}