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
+}