update multiaddr for ipfs addrs
Juan Batiz-Benet committed
Jan 20, 2015 at 12:29 UTC
6f9c297f0876d883f102e4fe09c60c61d5712d36
7 files changed
+116
-41
Godeps/Godeps.json
+2
-2
@@ -167,8 +167,8 @@
167
},
168
{
169
"ImportPath": "github.com/jbenet/go-multiaddr",
170
- "Comment": "0.1.2-34-g0d7b54b",
171
- "Rev": "0d7b54ba432fda14bac37cdad717bd6270eacc85"
170
+ "Comment": "0.1.2-38-gc13f11b",
171
+ "Rev": "c13f11bbfe6439771f4df7bfb330f686826144e8"
172
},
173
{
174
"ImportPath": "github.com/jbenet/go-multiaddr-net",
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/.travis.yml
+1
-2
@@ -1,10 +1,9 @@
1
language: go
2
3
go:
4
- - 1.2
4
- 1.3
5
- release
6
- tip
7
8
script:
10
- - go test -v ./...
9
+ - go test -race -cpu=5 -v ./...
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go
+77
-23
@@ -2,10 +2,13 @@ package multiaddr
2
3
import (
4
"encoding/binary"
5
+ "errors"
6
"fmt"
7
"net"
8
"strconv"
9
"strings"
10
+
11
+ mh "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash"
12
)
13
14
func stringToBytes(s string) ([]byte, error) {
@@ -31,17 +34,19 @@ func stringToBytes(s string) ([]byte, error) {
34
b = append(b, CodeToVarint(p.Code)...)
35
sp = sp[1:]
36
34
- if p.Size > 0 {
35
- if len(sp) < 1 {
36
- return nil, fmt.Errorf("protocol requires address, none given: %s", p.Name)
37
- }
38
- a, err := addressStringToBytes(p, sp[0])
39
- if err != nil {
40
- return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err)
41
- }
42
- b = append(b, a...)
43
- sp = sp[1:]
37
+ if p.Size == 0 { // no length.
38
+ continue
39
+ }
40
+
41
+ if len(sp) < 1 {
42
+ return nil, fmt.Errorf("protocol requires address, none given: %s", p.Name)
43
+ }
44
+ a, err := addressStringToBytes(p, sp[0])
45
+ if err != nil {
46
+ return nil, fmt.Errorf("failed to parse %s: %s %s", p.Name, sp[0], err)
47
}
48
+ b = append(b, a...)
49
+ sp = sp[1:]
50
}
51
return b, nil
52
}
@@ -51,7 +56,14 @@ func bytesToString(b []byte) (ret string, err error) {
56
defer func() {
57
if e := recover(); e != nil {
58
ret = ""
54
- err = e.(error)
59
+ switch e := e.(type) {
60
+ case error:
61
+ err = e
62
+ case string:
63
+ err = errors.New(e)
64
+ default:
65
+ err = fmt.Errorf("%v", e)
66
+ }
67
}
68
}()
69
@@ -65,20 +77,38 @@ func bytesToString(b []byte) (ret string, err error) {
77
if p.Code == 0 {
78
return "", fmt.Errorf("no protocol with code %d", code)
79
}
68
- s = strings.Join([]string{s, "/", p.Name}, "")
80
+ s += "/" + p.Name
81
70
- if p.Size > 0 {
71
- a := addressBytesToString(p, b[:(p.Size/8)])
72
- if len(a) > 0 {
73
- s = strings.Join([]string{s, "/", a}, "")
74
- }
75
- b = b[(p.Size / 8):]
82
+ if p.Size == 0 {
83
+ continue
84
+ }
85
+
86
+ size := sizeForAddr(p, b)
87
+ a, err := addressBytesToString(p, b[:size])
88
+ if err != nil {
89
+ return "", err
90
}
91
+ if len(a) > 0 {
92
+ s += "/" + a
93
+ }
94
+ b = b[size:]
95
}
96
97
return s, nil
98
}
99
100
+func sizeForAddr(p Protocol, b []byte) int {
101
+ switch {
102
+ case p.Size > 0:
103
+ return (p.Size / 8)
104
+ case p.Size == 0:
105
+ return 0
106
+ default:
107
+ size, n := ReadVarintCode(b)
108
+ return size + n
109
+ }
110
+}
111
+
112
func bytesSplit(b []byte) (ret [][]byte, err error) {
113
// panic handler, in case we try accessing bytes incorrectly.
114
defer func() {
@@ -96,7 +126,8 @@ func bytesSplit(b []byte) (ret [][]byte, err error) {
126
return [][]byte{}, fmt.Errorf("no protocol with code %d", b[0])
127
}
128
99
- length := n + (p.Size / 8)
129
+ size := sizeForAddr(p, b[n:])
130
+ length := n + size
131
ret = append(ret, b[:length])
132
b = b[length:]
133
}
@@ -133,23 +164,46 @@ func addressStringToBytes(p Protocol, s string) ([]byte, error) {
164
b := make([]byte, 2)
165
binary.BigEndian.PutUint16(b, uint16(i))
166
return b, nil
167
+
168
+ case P_IPFS: // ipfs
169
+ // the address is a varint prefixed multihash string representation
170
+ m, err := mh.FromB58String(s)
171
+ if err != nil {
172
+ return nil, fmt.Errorf("failed to parse ipfs addr: %s %s", s, err)
173
+ }
174
+ size := CodeToVarint(len(m))
175
+ b := append(size, m...)
176
+ return b, nil
177
}
178
179
return []byte{}, fmt.Errorf("failed to parse %s addr: unknown", p.Name)
180
}
181
141
-func addressBytesToString(p Protocol, b []byte) string {
182
+func addressBytesToString(p Protocol, b []byte) (string, error) {
183
switch p.Code {
184
185
// ipv4,6
186
case P_IP4, P_IP6:
146
- return net.IP(b).String()
187
+ return net.IP(b).String(), nil
188
189
// tcp udp dccp sctp
190
case P_TCP, P_UDP, P_DCCP, P_SCTP:
191
i := binary.BigEndian.Uint16(b)
151
- return strconv.Itoa(int(i))
192
+ return strconv.Itoa(int(i)), nil
193
+
194
+ case P_IPFS: // ipfs
195
+ // the address is a varint-prefixed multihash string representation
196
+ size, n := ReadVarintCode(b)
197
+ b = b[n:]
198
+ if len(b) != size {
199
+ panic("inconsistent lengths")
200
+ }
201
+ m, err := mh.Cast(b)
202
+ if err != nil {
203
+ return "", err
204
+ }
205
+ return m.B58String(), nil
206
}
207
154
- return ""
208
+ return "", fmt.Errorf("unknown protocol")
209
}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go
+5
-1
@@ -64,6 +64,7 @@ func (m *multiaddr) Protocols() []Protocol {
64
}
65
}()
66
67
+ size := 0
68
ps := []Protocol{}
69
b := m.bytes[:]
70
for len(b) > 0 {
@@ -75,7 +76,10 @@ func (m *multiaddr) Protocols() []Protocol {
76
panic(fmt.Errorf("no protocol with code %d", b[0]))
77
}
78
ps = append(ps, p)
78
- b = b[n+(p.Size/8):]
79
+ b = b[n:]
80
+
81
+ size = sizeForAddr(p, b)
82
+ b = b[size:]
83
}
84
return ps
85
}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go
+10
-2
@@ -32,11 +32,13 @@ func TestConstructFails(t *testing.T) {
32
"/ip4/127.0.0.1/udp",
33
"/ip4/127.0.0.1/tcp/jfodsajfidosajfoidsa",
34
"/ip4/127.0.0.1/tcp",
35
+ "/ip4/127.0.0.1/ipfs",
36
+ "/ip4/127.0.0.1/ipfs/tcp",
37
}
38
39
for _, a := range cases {
40
if _, err := NewMultiaddr(a); err == nil {
39
- t.Errorf("should have failed: %s", a)
41
+ t.Errorf("should have failed: %s - %s", a, err)
42
}
43
}
44
}
@@ -55,18 +57,24 @@ func TestConstructSucceeds(t *testing.T) {
57
"/sctp/1234",
58
"/udp/65535",
59
"/tcp/65535",
60
+ "/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
61
"/udp/1234/sctp/1234",
62
"/udp/1234/udt",
63
"/udp/1234/utp",
64
+ "/tcp/1234/http",
65
+ "/tcp/1234/https",
66
+ "/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
67
"/ip4/127.0.0.1/udp/1234",
68
"/ip4/127.0.0.1/udp/0",
69
"/ip4/127.0.0.1/tcp/1234",
70
"/ip4/127.0.0.1/tcp/1234/",
71
+ "/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC",
72
+ "/ip4/127.0.0.1/ipfs/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/tcp/1234",
73
}
74
75
for _, a := range cases {
76
if _, err := NewMultiaddr(a); err != nil {
69
- t.Errorf("should have succeeded: %s", a)
77
+ t.Errorf("should have succeeded: %s -- %s", a, err)
78
}
79
}
80
}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.csv
+1
@@ -7,5 +7,6 @@ code size name
7
132 16 sctp
8
301 0 udt
9
302 0 utp
10
+421 V ipfs
11
480 0 http
12
443 0 https
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/protocols.go
+20
-11
@@ -9,7 +9,7 @@ import (
9
// Protocol is a Multiaddr protocol description structure.
10
type Protocol struct {
11
Code int
12
- Size int
12
+ Size int // a size of -1 indicates a length-prefixed variable size
13
Name string
14
VCode []byte
15
}
@@ -19,14 +19,22 @@ type Protocol struct {
19
// 2. ensuring errors in the csv don't screw up code.
20
// 3. changing a number has to happen in two places.
21
const (
22
- P_IP4 = 4
23
- P_TCP = 6
24
- P_UDP = 17
25
- P_DCCP = 33
26
- P_IP6 = 41
27
- P_SCTP = 132
28
- P_UTP = 301
29
- P_UDT = 302
22
+ P_IP4 = 4
23
+ P_TCP = 6
24
+ P_UDP = 17
25
+ P_DCCP = 33
26
+ P_IP6 = 41
27
+ P_SCTP = 132
28
+ P_UTP = 301
29
+ P_UDT = 302
30
+ P_IPFS = 421
31
+ P_HTTP = 480
32
+ P_HTTPS = 443
33
+)
34
+
35
+// These are special sizes
36
+const (
37
+ LengthPrefixedVarSize = -1
38
)
39
40
// Protocols is the list of multiaddr protocols supported by this module.
@@ -40,8 +48,9 @@ var Protocols = []Protocol{
48
Protocol{P_SCTP, 16, "sctp", CodeToVarint(P_SCTP)},
49
Protocol{P_UTP, 0, "utp", CodeToVarint(P_UTP)},
50
Protocol{P_UDT, 0, "udt", CodeToVarint(P_UDT)},
43
- // {480, 0, "http"},
44
- // {443, 0, "https"},
51
+ Protocol{P_HTTP, 0, "http", CodeToVarint(P_HTTP)},
52
+ Protocol{P_HTTPS, 0, "https", CodeToVarint(P_HTTPS)},
53
+ Protocol{P_IPFS, LengthPrefixedVarSize, "ipfs", CodeToVarint(P_IPFS)},
54
}
55
56
// ProtocolWithName returns the Protocol description with given string name.