Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
mf
go-multiaddr
Commits
86e5d145
Unverified
Commit
86e5d145
authored
Oct 21, 2018
by
vyzo
Committed by
GitHub
Oct 21, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #42 from mwnx/ip6z
Add "ip6%" multiaddr support (IPv6 with zone ID)
parents
3ce601ca
a1defdc5
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
153 additions
and
51 deletions
+153
-51
convert.go
convert.go
+35
-9
convert_test.go
convert_test.go
+40
-19
ip.go
ip.go
+46
-23
net_test.go
net_test.go
+32
-0
No files found.
convert.go
View file @
86e5d145
...
...
@@ -65,24 +65,39 @@ func parseBasicNetMaddr(maddr ma.Multiaddr) (net.Addr, error) {
return
nil
,
fmt
.
Errorf
(
"network not supported: %s"
,
network
)
}
// FromIP converts a net.IP type to a Multiaddr.
func
FromIP
(
ip
net
.
IP
)
(
ma
.
Multiaddr
,
error
)
{
var
proto
string
func
FromIPAndZone
(
ip
net
.
IP
,
zone
string
)
(
ma
.
Multiaddr
,
error
)
{
switch
{
case
ip
.
To4
()
!=
nil
:
proto
=
"ip4"
return
ma
.
NewComponent
(
"ip4"
,
ip
.
String
())
case
ip
.
To16
()
!=
nil
:
proto
=
"ip6"
ip6
,
err
:=
ma
.
NewComponent
(
"ip6"
,
ip
.
String
())
if
err
!=
nil
{
return
nil
,
err
}
if
zone
==
""
{
return
ip6
,
nil
}
else
{
zone
,
err
:=
ma
.
NewComponent
(
"ip6zone"
,
zone
)
if
err
!=
nil
{
return
nil
,
err
}
return
zone
.
Encapsulate
(
ip6
),
nil
}
default
:
return
nil
,
errIncorrectNetAddr
}
return
ma
.
NewComponent
(
proto
,
ip
.
String
())
}
// FromIP converts a net.IP type to a Multiaddr.
func
FromIP
(
ip
net
.
IP
)
(
ma
.
Multiaddr
,
error
)
{
return
FromIPAndZone
(
ip
,
""
)
}
// DialArgs is a convenience function returning arguments for use in net.Dial
func
DialArgs
(
m
ma
.
Multiaddr
)
(
string
,
string
,
error
)
{
var
(
zone
,
network
,
ip
,
port
string
err
error
)
ma
.
ForEach
(
m
,
func
(
c
ma
.
Component
)
bool
{
...
...
@@ -90,6 +105,10 @@ func DialArgs(m ma.Multiaddr) (string, string, error) {
case
""
:
switch
c
.
Protocol
()
.
Code
{
case
ma
.
P_IP6ZONE
:
if
zone
!=
""
{
err
=
fmt
.
Errorf
(
"%s has multiple zones"
,
m
)
return
false
}
zone
=
c
.
Value
()
return
true
case
ma
.
P_IP6
:
...
...
@@ -97,6 +116,10 @@ func DialArgs(m ma.Multiaddr) (string, string, error) {
ip
=
c
.
Value
()
return
true
case
ma
.
P_IP4
:
if
zone
!=
""
{
err
=
fmt
.
Errorf
(
"%s has ip4 with zone"
,
m
)
return
false
}
network
=
"ip4"
ip
=
c
.
Value
()
return
true
...
...
@@ -125,6 +148,9 @@ func DialArgs(m ma.Multiaddr) (string, string, error) {
// Done.
return
false
})
if
err
!=
nil
{
return
""
,
""
,
err
}
switch
network
{
case
"ip6"
:
if
zone
!=
""
{
...
...
@@ -152,7 +178,7 @@ func parseTCPNetAddr(a net.Addr) (ma.Multiaddr, error) {
}
// Get IP Addr
ipm
,
err
:=
FromIP
(
ac
.
IP
)
ipm
,
err
:=
FromIP
AndZone
(
ac
.
IP
,
ac
.
Zone
)
if
err
!=
nil
{
return
nil
,
errIncorrectNetAddr
}
...
...
@@ -174,7 +200,7 @@ func parseUDPNetAddr(a net.Addr) (ma.Multiaddr, error) {
}
// Get IP Addr
ipm
,
err
:=
FromIP
(
ac
.
IP
)
ipm
,
err
:=
FromIP
AndZone
(
ac
.
IP
,
ac
.
Zone
)
if
err
!=
nil
{
return
nil
,
errIncorrectNetAddr
}
...
...
@@ -194,7 +220,7 @@ func parseIPNetAddr(a net.Addr) (ma.Multiaddr, error) {
if
!
ok
{
return
nil
,
errIncorrectNetAddr
}
return
FromIP
(
ac
.
IP
)
return
FromIP
AndZone
(
ac
.
IP
,
ac
.
Zone
)
}
func
parseIPPlusNetAddr
(
a
net
.
Addr
)
(
ma
.
Multiaddr
,
error
)
{
...
...
convert_test.go
View file @
86e5d145
...
...
@@ -90,18 +90,25 @@ func TestFromUDP(t *testing.T) {
func
TestThinWaist
(
t
*
testing
.
T
)
{
addrs
:=
map
[
string
]
bool
{
"/ip4/127.0.0.1/udp/1234"
:
true
,
"/ip4/127.0.0.1/tcp/1234"
:
true
,
"/ip4/127.0.0.1/udp/1234/tcp/1234"
:
true
,
"/ip4/127.0.0.1/tcp/12345/ip4/1.2.3.4"
:
true
,
"/ip6/::1/tcp/80"
:
true
,
"/ip6/::1/udp/80"
:
true
,
"/ip6/::1"
:
true
,
"/tcp/1234/ip4/1.2.3.4"
:
false
,
"/tcp/1234"
:
false
,
"/tcp/1234/udp/1234"
:
false
,
"/ip4/1.2.3.4/ip4/2.3.4.5"
:
true
,
"/ip6/::1/ip4/2.3.4.5"
:
true
,
"/ip4/127.0.0.1/udp/1234"
:
true
,
"/ip4/127.0.0.1/tcp/1234"
:
true
,
"/ip4/127.0.0.1/udp/1234/tcp/1234"
:
true
,
"/ip4/127.0.0.1/tcp/12345/ip4/1.2.3.4"
:
true
,
"/ip6/::1/tcp/80"
:
true
,
"/ip6/::1/udp/80"
:
true
,
"/ip6/::1"
:
true
,
"/ip6zone/hello/ip6/fe80::1/tcp/80"
:
true
,
"/ip6zone/hello/ip6/fe80::1"
:
true
,
"/tcp/1234/ip4/1.2.3.4"
:
false
,
"/tcp/1234"
:
false
,
"/tcp/1234/udp/1234"
:
false
,
"/ip4/1.2.3.4/ip4/2.3.4.5"
:
true
,
"/ip6/fe80::1/ip4/2.3.4.5"
:
true
,
"/ip6zone/hello/ip6/fe80::1/ip4/2.3.4.5"
:
true
,
// Invalid ip6zone usage:
"/ip6zone/hello"
:
false
,
"/ip6zone/hello/ip4/1.1.1.1"
:
false
,
}
for
a
,
res
:=
range
addrs
{
...
...
@@ -120,7 +127,7 @@ func TestDialArgs(t *testing.T) {
test
:=
func
(
e_maddr
,
e_nw
,
e_host
string
)
{
m
,
err
:=
ma
.
NewMultiaddr
(
e_maddr
)
if
err
!=
nil
{
t
.
Fatal
(
"failed to construct"
,
"/ip4/127.0.0.1/udp/1234"
,
e_maddr
)
t
.
Fatal
(
"failed to construct"
,
e_maddr
)
}
nw
,
host
,
err
:=
DialArgs
(
m
)
...
...
@@ -137,14 +144,28 @@ func TestDialArgs(t *testing.T) {
}
}
test_error
:=
func
(
e_maddr
string
)
{
m
,
err
:=
ma
.
NewMultiaddr
(
e_maddr
)
if
err
!=
nil
{
t
.
Fatal
(
"failed to construct"
,
e_maddr
)
}
_
,
_
,
err
=
DialArgs
(
m
)
if
err
==
nil
{
t
.
Fatal
(
"expected DialArgs to fail on"
,
e_maddr
)
}
}
test
(
"/ip4/127.0.0.1/udp/1234"
,
"udp4"
,
"127.0.0.1:1234"
)
test
(
"/ip4/127.0.0.1/tcp/4321"
,
"tcp4"
,
"127.0.0.1:4321"
)
test
(
"/ip6/::1/udp/1234"
,
"udp6"
,
"[::1]:1234"
)
test
(
"/ip6/::1/tcp/4321"
,
"tcp6"
,
"[::1]:4321"
)
test
(
"/ip6/::1"
,
"ip6"
,
"::1"
)
// Just an IP
test
(
"/ip4/1.2.3.4"
,
"ip4"
,
"1.2.3.4"
)
// Just an IP
test
(
"/ip6zone/foo/ip6/::1/tcp/4321"
,
"tcp6"
,
"[::1%foo]:4321"
)
// zone
test
(
"/ip6zone/foo/ip6/::1"
,
"ip6"
,
"::1%foo"
)
// no TCP
test
(
"/ip6zone/foo/ip6/::1/ip6zone/bar"
,
"ip6"
,
"::1%foo"
)
// IP over IP
test
(
"/ip6zone/foo/ip4/127.0.0.1/ip6zone/bar"
,
"ip4"
,
"127.0.0.1"
)
// Skip zones in IP
test
(
"/ip6/::1"
,
"ip6"
,
"::1"
)
// Just an IP
test
(
"/ip4/1.2.3.4"
,
"ip4"
,
"1.2.3.4"
)
// Just an IP
test
(
"/ip6zone/foo/ip6/::1/tcp/4321"
,
"tcp6"
,
"[::1%foo]:4321"
)
// zone
test
(
"/ip6zone/foo/ip6/::1/udp/4321"
,
"udp6"
,
"[::1%foo]:4321"
)
// zone
test
(
"/ip6zone/foo/ip6/::1"
,
"ip6"
,
"::1%foo"
)
// no TCP
test_error
(
"/ip6zone/foo/ip4/127.0.0.1"
)
// IP4 doesn't take zone
test
(
"/ip6zone/foo/ip6/::1/ip6zone/bar"
,
"ip6"
,
"::1%foo"
)
// IP over IP
test_error
(
"/ip6zone/foo/ip6zone/bar/ip6/::1"
)
// Only one zone per IP6
}
ip.go
View file @
86e5d145
...
...
@@ -27,6 +27,10 @@ var (
// IsThinWaist returns whether a Multiaddr starts with "Thin Waist" Protocols.
// This means: /{IP4, IP6}[/{TCP, UDP}]
func
IsThinWaist
(
m
ma
.
Multiaddr
)
bool
{
m
=
zoneless
(
m
)
if
m
==
nil
{
return
false
}
p
:=
m
.
Protocols
()
// nothing? not even a waist.
...
...
@@ -52,9 +56,14 @@ func IsThinWaist(m ma.Multiaddr) bool {
}
// IsIPLoopback returns whether a Multiaddr is a "Loopback" IP address
// This means either /ip4/127.*.*.*, /ip6/::1, or /ip6/::ffff:127.*.*.*.*
// This means either /ip4/127.*.*.*, /ip6/::1, or /ip6/::ffff:127.*.*.*.*,
// or /ip6zone/<any value>/ip6/<one of the preceding ip6 values>
func
IsIPLoopback
(
m
ma
.
Multiaddr
)
bool
{
m
=
zoneless
(
m
)
c
,
rest
:=
ma
.
SplitFirst
(
m
)
if
c
==
nil
{
return
false
}
if
rest
!=
nil
{
// Not *just* an IPv4 addr
return
false
...
...
@@ -66,33 +75,47 @@ func IsIPLoopback(m ma.Multiaddr) bool {
return
false
}
// IsIP6LinkLocal returns if a an IPv6 link-local multiaddress (with zero or
// more leading zones). These addresses are non routable.
// IsIP6LinkLocal returns whether a Multiaddr starts with an IPv6 link-local
// multiaddress (with zero or one leading zone). These addresses are non
// routable.
func
IsIP6LinkLocal
(
m
ma
.
Multiaddr
)
bool
{
matched
:=
false
ma
.
ForEach
(
m
,
func
(
c
ma
.
Component
)
bool
{
// Too much.
if
matched
{
matched
=
false
return
false
}
switch
c
.
Protocol
()
.
Code
{
case
ma
.
P_IP6ZONE
:
return
true
case
ma
.
P_IP6
:
ip
:=
net
.
IP
(
c
.
RawValue
())
matched
=
ip
.
IsLinkLocalMulticast
()
||
ip
.
IsLinkLocalUnicast
()
return
true
default
:
return
false
}
})
return
matched
m
=
zoneless
(
m
)
c
,
_
:=
ma
.
SplitFirst
(
m
)
if
c
==
nil
||
c
.
Protocol
()
.
Code
!=
ma
.
P_IP6
{
return
false
}
ip
:=
net
.
IP
(
c
.
RawValue
())
return
ip
.
IsLinkLocalMulticast
()
||
ip
.
IsLinkLocalUnicast
()
}
// IsIPUnspecified returns whether a Multiaddr is am Unspecified IP address
// This means either /ip4/0.0.0.0 or /ip6/::
func
IsIPUnspecified
(
m
ma
.
Multiaddr
)
bool
{
m
=
zoneless
(
m
)
if
m
==
nil
{
return
false
}
return
IP4Unspecified
.
Equal
(
m
)
||
IP6Unspecified
.
Equal
(
m
)
}
// If m matches [zone,ip6,...], return [ip6,...]
// else if m matches [], [zone], or [zone,...], return nil
// else return m
func
zoneless
(
m
ma
.
Multiaddr
)
ma
.
Multiaddr
{
head
,
tail
:=
ma
.
SplitFirst
(
m
)
if
head
==
nil
{
return
nil
}
if
head
.
Protocol
()
.
Code
==
ma
.
P_IP6ZONE
{
if
tail
==
nil
{
return
nil
}
tailhead
,
_
:=
ma
.
SplitFirst
(
tail
)
if
tailhead
.
Protocol
()
.
Code
!=
ma
.
P_IP6
{
return
nil
}
return
tail
}
else
{
return
m
}
}
net_test.go
View file @
86e5d145
...
...
@@ -175,12 +175,20 @@ func TestListenAddrs(t *testing.T) {
test
(
"/ip4/0.0.0.0/tcp/4324"
,
""
,
true
)
test
(
"/ip4/0.0.0.0/udp/4325"
,
""
,
false
)
test
(
"/ip4/0.0.0.0/udp/4326/udt"
,
""
,
false
)
test
(
"/ip6/::1/tcp/4324"
,
""
,
true
)
test
(
"/ip6/::1/udp/4325"
,
""
,
false
)
test
(
"/ip6/::1/udp/4326/udt"
,
""
,
false
)
test
(
"/ip6/::/tcp/4324"
,
""
,
true
)
test
(
"/ip6/::/udp/4325"
,
""
,
false
)
test
(
"/ip6/::/udp/4326/udt"
,
""
,
false
)
/* "An implementation should also support the concept of a "default"
* zone for each scope. And, when supported, the index value zero
* at each scope SHOULD be reserved to mean "use the default zone"."
* -- rfc4007. So, this _should_ work everywhere(?). */
test
(
"/ip6zone/0/ip6/::1/tcp/4324"
,
"/ip6/::1/tcp/4324"
,
true
)
test
(
"/ip6zone/0/ip6/::1/udp/4324"
,
""
,
false
)
}
func
TestListenAndDial
(
t
*
testing
.
T
)
{
...
...
@@ -345,6 +353,22 @@ func TestIPLoopback(t *testing.T) {
if
IsIPLoopback
(
newMultiaddr
(
t
,
"/ip6/::fffa:127.99.3.2"
))
{
t
.
Error
(
"IsIPLoopback false positive (/ip6/::fffa:127.99.3.2)"
)
}
if
!
IsIPLoopback
(
newMultiaddr
(
t
,
"/ip6zone/0/ip6/::1"
))
{
t
.
Error
(
"IsIPLoopback failed (/ip6zone/0/ip6/::1)"
)
}
if
!
IsIPLoopback
(
newMultiaddr
(
t
,
"/ip6zone/xxx/ip6/::1"
))
{
t
.
Error
(
"IsIPLoopback failed (/ip6zone/xxx/ip6/::1)"
)
}
if
IsIPLoopback
(
newMultiaddr
(
t
,
"/ip6zone/0/ip6/::1/tcp/3333"
))
{
t
.
Error
(
"IsIPLoopback failed (/ip6zone/0/ip6/::1/tcp/3333)"
)
}
if
IsIPLoopback
(
newMultiaddr
(
t
,
"/ip6zone/0/ip6/1::1"
))
{
t
.
Errorf
(
"IsIPLoopback false positive (/ip6zone/0/ip6/1::1)"
)
}
}
func
TestIPUnspecified
(
t
*
testing
.
T
)
{
...
...
@@ -363,6 +387,10 @@ func TestIPUnspecified(t *testing.T) {
if
!
IsIPUnspecified
(
IP6Unspecified
)
{
t
.
Error
(
"IsIPUnspecified failed (IP6Unspecified)"
)
}
if
!
IsIPUnspecified
(
newMultiaddr
(
t
,
"/ip6zone/xxx/ip6/::"
))
{
t
.
Error
(
"IsIPUnspecified failed (/ip6zone/xxx/ip6/::)"
)
}
}
func
TestIP6LinkLocal
(
t
*
testing
.
T
)
{
...
...
@@ -373,6 +401,10 @@ func TestIP6LinkLocal(t *testing.T) {
t
.
Errorf
(
"IsIP6LinkLocal failed (%s != %v)"
,
m
,
isLinkLocal
)
}
}
if
!
IsIP6LinkLocal
(
newMultiaddr
(
t
,
"/ip6zone/hello/ip6/fe80::9999"
))
{
t
.
Error
(
"IsIP6LinkLocal failed (/ip6/fe80::9999)"
)
}
}
func
TestConvertNetAddr
(
t
*
testing
.
T
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment