updated multiaddr
Juan Batiz-Benet committed
Nov 5, 2014 at 00:39 UTC
f0f202ed0857f11b5e28f09fa8be7b06efd4a2f0
14 files changed
+376
-50
Godeps/Godeps.json
+3
-3
@@ -1,6 +1,6 @@
1
{
2
"ImportPath": "github.com/jbenet/go-ipfs",
3
- "GoVersion": "go1.3.3",
3
+ "GoVersion": "go1.3",
4
"Packages": [
5
"./..."
6
],
@@ -102,8 +102,8 @@
102
},
103
{
104
"ImportPath": "github.com/jbenet/go-multiaddr",
105
- "Comment": "0.1.2-17-g68a2067",
106
- "Rev": "68a20675cb0829da219def0d90afe17a7219e8c7"
105
+ "Comment": "0.1.2-27-g62a88e0",
106
+ "Rev": "62a88e015e1bf5d6aaca29aec1aba0722f21c8d3"
107
},
108
{
109
"ImportPath": "github.com/jbenet/go-multihash",
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/README.md
-10
@@ -34,16 +34,6 @@ addr.Protocols()
34
// }
35
```
36
37
-### Other formats
38
-
39
-```go
40
-// handles the stupid url version too
41
-m = ma.NewUrl("udp4://127.0.0.1:1234")
42
-// <Multiaddr /ip4/127.0.0.1/udp/1234>
43
-m.Url(buf)
44
-// udp4://127.0.0.1:1234
45
-```
46
-
37
### En/decapsulate
38
39
```go
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/codec.go
+24
@@ -67,6 +67,30 @@ func bytesToString(b []byte) (ret string, err error) {
67
return s, nil
68
}
69
70
+func bytesSplit(b []byte) (ret [][]byte, err error) {
71
+ // panic handler, in case we try accessing bytes incorrectly.
72
+ defer func() {
73
+ if e := recover(); e != nil {
74
+ ret = [][]byte{}
75
+ err = e.(error)
76
+ }
77
+ }()
78
+
79
+ ret = [][]byte{}
80
+ for len(b) > 0 {
81
+ p := ProtocolWithCode(int(b[0]))
82
+ if p == nil {
83
+ return [][]byte{}, fmt.Errorf("no protocol with code %d", b[0])
84
+ }
85
+
86
+ length := 1 + (p.Size / 8)
87
+ ret = append(ret, b[:length])
88
+ b = b[length:]
89
+ }
90
+
91
+ return ret, nil
92
+}
93
+
94
func addressStringToBytes(p *Protocol, s string) []byte {
95
switch p.Code {
96
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr.go
+4
-4
@@ -84,10 +84,10 @@ func (m *multiaddr) Encapsulate(o Multiaddr) Multiaddr {
84
mb := m.bytes
85
ob := o.Bytes()
86
87
- var b bytes.Buffer
88
- b.Write(mb)
89
- b.Write(ob)
90
- return &multiaddr{bytes: b.Bytes()}
87
+ b := make([]byte, len(mb)+len(ob))
88
+ copy(b, mb)
89
+ copy(b[len(mb):], ob)
90
+ return &multiaddr{bytes: b}
91
}
92
93
// Decapsulate unwraps Multiaddr up until the given Multiaddr is found.
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr/multiaddr
Binary files /dev/null and b/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr/multiaddr differ
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr/multiaddr.go
new
+96
@@ -0,0 +1,96 @@
1
+package main
2
+
3
+import (
4
+ "encoding/hex"
5
+ "flag"
6
+ "fmt"
7
+ "os"
8
+
9
+ ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
10
+ manet "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net"
11
+)
12
+
13
+// flags
14
+var formats = []string{"string", "bytes", "hex", "slice"}
15
+var format string
16
+var hideLoopback bool
17
+
18
+func init() {
19
+ flag.Usage = func() {
20
+ fmt.Fprintf(os.Stderr, "usage: %s [<multiaddr>]\n\nFlags:\n", os.Args[0])
21
+ flag.PrintDefaults()
22
+ }
23
+
24
+ usage := fmt.Sprintf("output format, one of: %v", formats)
25
+ flag.StringVar(&format, "format", "string", usage)
26
+ flag.StringVar(&format, "f", "string", usage+" (shorthand)")
27
+ flag.BoolVar(&hideLoopback, "hide-loopback", false, "do not display loopback addresses")
28
+}
29
+
30
+func main() {
31
+ flag.Parse()
32
+ args := flag.Args()
33
+ if len(args) == 0 {
34
+ output(localAddresses()...)
35
+ } else {
36
+ output(address(args[0]))
37
+ }
38
+}
39
+
40
+func localAddresses() []ma.Multiaddr {
41
+ maddrs, err := manet.InterfaceMultiaddrs()
42
+ if err != nil {
43
+ die(err)
44
+ }
45
+
46
+ if !hideLoopback {
47
+ return maddrs
48
+ }
49
+
50
+ var maddrs2 []ma.Multiaddr
51
+ for _, a := range maddrs {
52
+ if !manet.IsIPLoopback(a) {
53
+ maddrs2 = append(maddrs2, a)
54
+ }
55
+ }
56
+
57
+ return maddrs2
58
+}
59
+
60
+func address(addr string) ma.Multiaddr {
61
+ m, err := ma.NewMultiaddr(addr)
62
+ if err != nil {
63
+ die(err)
64
+ }
65
+
66
+ return m
67
+}
68
+
69
+func output(ms ...ma.Multiaddr) {
70
+ for _, m := range ms {
71
+ fmt.Println(outfmt(m))
72
+ }
73
+}
74
+
75
+func outfmt(m ma.Multiaddr) string {
76
+ switch format {
77
+ case "string":
78
+ return m.String()
79
+ case "slice":
80
+ return fmt.Sprintf("%v", m.Bytes())
81
+ case "bytes":
82
+ return string(m.Bytes())
83
+ case "hex":
84
+ return "0x" + hex.EncodeToString(m.Bytes())
85
+ }
86
+
87
+ die("error: invalid format", format)
88
+ return ""
89
+}
90
+
91
+func die(v ...interface{}) {
92
+ fmt.Fprint(os.Stderr, v...)
93
+ fmt.Fprint(os.Stderr, "\n")
94
+ flag.Usage()
95
+ os.Exit(-1)
96
+}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/multiaddr_test.go
+43
@@ -91,6 +91,49 @@ func TestBytesToString(t *testing.T) {
91
testString("/ip4/127.0.0.1/udp/1234", "047f0000011104d2")
92
}
93
94
+func TestBytesSplitAndJoin(t *testing.T) {
95
+
96
+ testString := func(s string, res []string) {
97
+ m, err := NewMultiaddr(s)
98
+ if err != nil {
99
+ t.Error("failed to convert", s)
100
+ }
101
+
102
+ split := Split(m)
103
+ if len(split) != len(res) {
104
+ t.Error("not enough split components", split)
105
+ return
106
+ }
107
+
108
+ for i, a := range split {
109
+ if a.String() != res[i] {
110
+ t.Errorf("split component failed: %s != %s", a, res[i])
111
+ }
112
+ }
113
+
114
+ joined := Join(split...)
115
+ if !m.Equal(joined) {
116
+ t.Errorf("joined components failed: %s != %s", m, joined)
117
+ }
118
+
119
+ // modifying underlying bytes is fine.
120
+ m2 := m.(*multiaddr)
121
+ for i := range m2.bytes {
122
+ m2.bytes[i] = 0
123
+ }
124
+
125
+ for i, a := range split {
126
+ if a.String() != res[i] {
127
+ t.Errorf("split component failed: %s != %s", a, res[i])
128
+ }
129
+ }
130
+ }
131
+
132
+ testString("/ip4/1.2.3.4/udp/1234", []string{"/ip4/1.2.3.4", "/udp/1234"})
133
+ testString("/ip4/1.2.3.4/tcp/1/ip4/2.3.4.5/udp/2",
134
+ []string{"/ip4/1.2.3.4", "/tcp/1", "/ip4/2.3.4.5", "/udp/2"})
135
+}
136
+
137
func TestProtocols(t *testing.T) {
138
m, err := NewMultiaddr("/ip4/127.0.0.1/udp/1234")
139
if err != nil {
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert.go
+8
-28
@@ -1,4 +1,4 @@
1
-package net
1
+package manet
2
3
import (
4
"fmt"
@@ -62,6 +62,13 @@ func FromNetAddr(a net.Addr) (ma.Multiaddr, error) {
62
}
63
return FromIP(ac.IP)
64
65
+ case "ip+net":
66
+ ac, ok := a.(*net.IPNet)
67
+ if !ok {
68
+ return nil, errIncorrectNetAddr
69
+ }
70
+ return FromIP(ac.IP)
71
+
72
default:
73
return nil, fmt.Errorf("unknown network %v", a.Network())
74
}
@@ -123,30 +130,3 @@ func DialArgs(m ma.Multiaddr) (string, string, error) {
130
}
131
return network, host, nil
132
}
126
-
127
-// IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols.
128
-// This means: /{IP4, IP6}[/{TCP, UDP}]
129
-func IsThinWaist(m ma.Multiaddr) bool {
130
- p := m.Protocols()
131
-
132
- // nothing? not even a waist.
133
- if len(p) == 0 {
134
- return false
135
- }
136
-
137
- if p[0].Code != ma.P_IP4 && p[0].Code != ma.P_IP6 {
138
- return false
139
- }
140
-
141
- // only IP? still counts.
142
- if len(p) == 1 {
143
- return true
144
- }
145
-
146
- switch p[1].Code {
147
- case ma.P_TCP, ma.P_UDP, ma.P_IP4, ma.P_IP6:
148
- return true
149
- default:
150
- return false
151
- }
152
-}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/convert_test.go
+1
-1
@@ -1,4 +1,4 @@
1
-package net
1
+package manet
2
3
import (
4
"net"
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/doc.go
+2
-2
@@ -1,5 +1,5 @@
1
-// Package net provides Multiaddr specific versions of common
1
+// Package manet provides Multiaddr specific versions of common
2
// functions in stdlib's net package. This means wrappers of
3
// standard net symbols like net.Dial and net.Listen, as well
4
// as conversion to/from net.Addr.
5
-package net
5
+package manet
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/ip.go
new
+76
@@ -0,0 +1,76 @@
1
+package manet
2
+
3
+import (
4
+ "bytes"
5
+
6
+ ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
7
+)
8
+
9
+// Loopback Addresses
10
+var (
11
+ // IP4Loopback is the ip4 loopback multiaddr
12
+ IP4Loopback = ma.StringCast("/ip4/127.0.0.1")
13
+
14
+ // IP6Loopback is the ip6 loopback multiaddr
15
+ IP6Loopback = ma.StringCast("/ip6/::1")
16
+
17
+ // IP6LinkLocalLoopback is the ip6 link-local loopback multiaddr
18
+ IP6LinkLocalLoopback = ma.StringCast("/ip6/fe80::1")
19
+)
20
+
21
+// Unspecified Addresses (used for )
22
+var (
23
+ IP4Unspecified = ma.StringCast("/ip4/0.0.0.0")
24
+ IP6Unspecified = ma.StringCast("/ip6/::")
25
+)
26
+
27
+// IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols.
28
+// This means: /{IP4, IP6}[/{TCP, UDP}]
29
+func IsThinWaist(m ma.Multiaddr) bool {
30
+ p := m.Protocols()
31
+
32
+ // nothing? not even a waist.
33
+ if len(p) == 0 {
34
+ return false
35
+ }
36
+
37
+ if p[0].Code != ma.P_IP4 && p[0].Code != ma.P_IP6 {
38
+ return false
39
+ }
40
+
41
+ // only IP? still counts.
42
+ if len(p) == 1 {
43
+ return true
44
+ }
45
+
46
+ switch p[1].Code {
47
+ case ma.P_TCP, ma.P_UDP, ma.P_IP4, ma.P_IP6:
48
+ return true
49
+ default:
50
+ return false
51
+ }
52
+}
53
+
54
+// IsIPLoopback returns whether a Multiaddr is a "Loopback" IP address
55
+// This means either /ip4/127.0.0.1 or /ip6/::1
56
+func IsIPLoopback(m ma.Multiaddr) bool {
57
+ b := m.Bytes()
58
+
59
+ // /ip4/127 prefix (_entire_ /8 is loopback...)
60
+ if bytes.HasPrefix(b, []byte{4, 127}) {
61
+ return true
62
+ }
63
+
64
+ // /ip6/::1
65
+ if IP6Loopback.Equal(m) || IP6LinkLocalLoopback.Equal(m) {
66
+ return true
67
+ }
68
+
69
+ return false
70
+}
71
+
72
+// IsIPUnspecified returns whether a Multiaddr is am Unspecified IP address
73
+// This means either /ip4/0.0.0.0 or /ip6/::
74
+func IsIPUnspecified(m ma.Multiaddr) bool {
75
+ return IP4Unspecified.Equal(m) || IP6Unspecified.Equal(m)
76
+}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net.go
+18
-1
@@ -1,4 +1,4 @@
1
-package net
1
+package manet
2
3
import (
4
"fmt"
@@ -216,3 +216,20 @@ func Listen(laddr ma.Multiaddr) (Listener, error) {
216
laddr: laddr,
217
}, nil
218
}
219
+
220
+// InterfaceMultiaddrs will return the addresses matching net.InterfaceAddrs
221
+func InterfaceMultiaddrs() ([]ma.Multiaddr, error) {
222
+ addrs, err := net.InterfaceAddrs()
223
+ if err != nil {
224
+ return nil, err
225
+ }
226
+
227
+ maddrs := make([]ma.Multiaddr, len(addrs))
228
+ for i, a := range addrs {
229
+ maddrs[i], err = FromNetAddr(a)
230
+ if err != nil {
231
+ return nil, err
232
+ }
233
+ }
234
+ return maddrs, nil
235
+}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/net/net_test.go
+45
-1
@@ -1,4 +1,4 @@
1
-package net
1
+package manet
2
3
import (
4
"bytes"
@@ -198,3 +198,47 @@ func TestListenAndDial(t *testing.T) {
198
cA.Close()
199
wg.Wait()
200
}
201
+
202
+func TestIPLoopback(t *testing.T) {
203
+ if IP4Loopback.String() != "/ip4/127.0.0.1" {
204
+ t.Error("IP4Loopback incorrect:", IP4Loopback)
205
+ }
206
+
207
+ if IP6Loopback.String() != "/ip6/::1" {
208
+ t.Error("IP6Loopback incorrect:", IP6Loopback)
209
+ }
210
+
211
+ if IP6LinkLocalLoopback.String() != "/ip6/fe80::1" {
212
+ t.Error("IP6LinkLocalLoopback incorrect:", IP6Loopback)
213
+ }
214
+
215
+ if !IsIPLoopback(IP4Loopback) {
216
+ t.Error("IsIPLoopback failed (IP4Loopback)")
217
+ }
218
+
219
+ if !IsIPLoopback(IP6Loopback) {
220
+ t.Error("IsIPLoopback failed (IP6Loopback)")
221
+ }
222
+
223
+ if !IsIPLoopback(IP6LinkLocalLoopback) {
224
+ t.Error("IsIPLoopback failed (IP6LinkLocalLoopback)")
225
+ }
226
+}
227
+
228
+func TestIPUnspecified(t *testing.T) {
229
+ if IP4Unspecified.String() != "/ip4/0.0.0.0" {
230
+ t.Error("IP4Unspecified incorrect:", IP4Unspecified)
231
+ }
232
+
233
+ if IP6Unspecified.String() != "/ip6/::" {
234
+ t.Error("IP6Unspecified incorrect:", IP6Unspecified)
235
+ }
236
+
237
+ if !IsIPUnspecified(IP4Unspecified) {
238
+ t.Error("IsIPUnspecified failed (IP4Unspecified)")
239
+ }
240
+
241
+ if !IsIPUnspecified(IP6Unspecified) {
242
+ t.Error("IsIPUnspecified failed (IP6Unspecified)")
243
+ }
244
+}
Godeps/_workspace/src/github.com/jbenet/go-multiaddr/util.go
new
+56
@@ -0,0 +1,56 @@
1
+package multiaddr
2
+
3
+import "fmt"
4
+
5
+// Split returns the sub-address portions of a multiaddr.
6
+func Split(m Multiaddr) []Multiaddr {
7
+ split, err := bytesSplit(m.Bytes())
8
+ if err != nil {
9
+ panic(fmt.Errorf("invalid multiaddr %s", m.String()))
10
+ }
11
+
12
+ addrs := make([]Multiaddr, len(split))
13
+ for i, addr := range split {
14
+ addrs[i] = &multiaddr{bytes: addr}
15
+ }
16
+ return addrs
17
+}
18
+
19
+// Join returns a combination of addresses.
20
+func Join(ms ...Multiaddr) Multiaddr {
21
+
22
+ length := 0
23
+ bs := make([][]byte, len(ms))
24
+ for i, m := range ms {
25
+ bs[i] = m.Bytes()
26
+ length += len(bs[i])
27
+ }
28
+
29
+ bidx := 0
30
+ b := make([]byte, length)
31
+ for _, mb := range bs {
32
+ for i := range mb {
33
+ b[bidx] = mb[i]
34
+ bidx++
35
+ }
36
+ }
37
+ return &multiaddr{bytes: b}
38
+}
39
+
40
+// Cast re-casts a byte slice as a multiaddr. will panic if it fails to parse.
41
+func Cast(b []byte) Multiaddr {
42
+ _, err := bytesToString(b)
43
+ if err != nil {
44
+ panic(fmt.Errorf("multiaddr failed to parse: %s", err))
45
+ }
46
+ return &multiaddr{bytes: b}
47
+}
48
+
49
+// StringCast like Cast, but parses a string. Will also panic if it fails to parse.
50
+func StringCast(s string) Multiaddr {
51
+ m, err := NewMultiaddr(s)
52
+ if err != nil {
53
+ panic(fmt.Errorf("multiaddr failed to parse: %s", err))
54
+ }
55
+ return m
56
+}