mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-05-11 22:09:32 +00:00
Better support for ivp6 and more tests
This commit is contained in:
parent
24c1515778
commit
8110abcb9d
@ -137,7 +137,12 @@ proc getRoutePrefSrc(bindIp: IpAddress): (Option[IpAddress], PrefSrcStatus) =
|
||||
let bindAddress = initTAddress(bindIp, Port(0))
|
||||
|
||||
if bindAddress.isAnyLocal():
|
||||
let ip = getRouteIpv4()
|
||||
let ip =
|
||||
if bindIp.family == IpAddressFamily.IPv6:
|
||||
getRouteIpv6()
|
||||
else:
|
||||
getRouteIpv4()
|
||||
|
||||
if ip.isErr():
|
||||
# No route was found, log error and continue without IP.
|
||||
error "No routable IP address found, check your network connection",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{.push raises: [].}
|
||||
|
||||
import std/[net, tables, hashes], pkg/results, chronos, chronicles
|
||||
import std/[net, tables, hashes, options], pkg/results, chronos, chronicles
|
||||
|
||||
import pkg/libp2p
|
||||
|
||||
@ -10,32 +10,6 @@ type NatStrategy* = enum
|
||||
NatPmp
|
||||
NatNone
|
||||
|
||||
type IpLimits* = object
|
||||
limit*: uint
|
||||
ips: Table[IpAddress, uint]
|
||||
|
||||
func hash*(ip: IpAddress): Hash =
|
||||
case ip.family
|
||||
of IpAddressFamily.IPv6:
|
||||
hash(ip.address_v6)
|
||||
of IpAddressFamily.IPv4:
|
||||
hash(ip.address_v4)
|
||||
|
||||
func inc*(ipLimits: var IpLimits, ip: IpAddress): bool =
|
||||
let val = ipLimits.ips.getOrDefault(ip, 0)
|
||||
if val < ipLimits.limit:
|
||||
ipLimits.ips[ip] = val + 1
|
||||
true
|
||||
else:
|
||||
false
|
||||
|
||||
func dec*(ipLimits: var IpLimits, ip: IpAddress) =
|
||||
let val = ipLimits.ips.getOrDefault(ip, 0)
|
||||
if val == 1:
|
||||
ipLimits.ips.del(ip)
|
||||
elif val > 1:
|
||||
ipLimits.ips[ip] = val - 1
|
||||
|
||||
func isGlobalUnicast*(address: TransportAddress): bool =
|
||||
if address.isGlobal() and address.isUnicast(): true else: false
|
||||
|
||||
@ -43,18 +17,11 @@ func isGlobalUnicast*(address: IpAddress): bool =
|
||||
let a = initTAddress(address, Port(0))
|
||||
a.isGlobalUnicast()
|
||||
|
||||
proc getRouteIpv4*(): Result[IpAddress, cstring] =
|
||||
# Avoiding Exception with initTAddress and can't make it work with static.
|
||||
# Note: `publicAddress` is only used an "example" IP to find the best route,
|
||||
# no data is send over the network to this IP!
|
||||
let
|
||||
publicAddress = TransportAddress(
|
||||
family: AddressFamily.IPv4, address_v4: [1'u8, 1, 1, 1], port: Port(0)
|
||||
)
|
||||
route = getBestRoute(publicAddress)
|
||||
proc getRoute(publicAddress: TransportAddress): Result[IpAddress, cstring] =
|
||||
let route = getBestRoute(publicAddress)
|
||||
|
||||
if route.source.isUnspecified():
|
||||
err("No best ipv4 route found")
|
||||
err("No best route found")
|
||||
else:
|
||||
let ip =
|
||||
try:
|
||||
@ -64,3 +31,42 @@ proc getRouteIpv4*(): Result[IpAddress, cstring] =
|
||||
error "Address conversion error", exception = e.name, msg = e.msg
|
||||
return err("Invalid IP address")
|
||||
ok(ip)
|
||||
|
||||
proc getRouteIpv4*(): Result[IpAddress, cstring] =
|
||||
# Avoiding Exception with initTAddress and can't make it work with static.
|
||||
# Note: `publicAddress` is only used an "example" IP to find the best route,
|
||||
# no data is send over the network to this IP!
|
||||
let publicAddress = TransportAddress(
|
||||
family: AddressFamily.IPv4, address_v4: [1'u8, 1, 1, 1], port: Port(0)
|
||||
)
|
||||
|
||||
return getRoute(publicAddress)
|
||||
|
||||
proc getRouteIpv6*(): Result[IpAddress, cstring] =
|
||||
# Note: `googleDnsIpv6` is only used as an "example" IP to find the best route,
|
||||
# no data is sent over the network to this IP!
|
||||
const googleDnsIpv6 = TransportAddress(
|
||||
family: AddressFamily.IPv6,
|
||||
# 2001:4860:4860::8888
|
||||
address_v6: [32'u8, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 136],
|
||||
port: Port(0),
|
||||
)
|
||||
|
||||
return getRoute(googleDnsIpv6)
|
||||
|
||||
# If bindIp is a anyLocal address (0.0.0.0 or ::),
|
||||
# the function will find the best ip address.
|
||||
# Otherwise, it will just return the ip as it is.
|
||||
proc getBestLocalAddress*(bindIp: IpAddress): Option[IpAddress] =
|
||||
let bindAddress = initTAddress(bindIp, Port(0))
|
||||
if bindAddress.isAnyLocal():
|
||||
let ip =
|
||||
if bindIp.family == IpAddressFamily.IPv6:
|
||||
getRouteIpv6()
|
||||
else:
|
||||
getRouteIpv4()
|
||||
if ip.isOk():
|
||||
return some(ip.get())
|
||||
return none(IpAddress)
|
||||
else:
|
||||
return some(bindIp)
|
||||
|
||||
@ -21,16 +21,18 @@ suite "NAT Address Tests":
|
||||
|
||||
# Expected results
|
||||
let
|
||||
expectedDiscoveryAddrs = @[
|
||||
MultiAddress.init("/ip4/8.8.8.8/udp/1234").expect("valid multiaddr"),
|
||||
MultiAddress.init("/ip4/8.8.8.8/udp/1234").expect("valid multiaddr"),
|
||||
MultiAddress.init("/ip4/8.8.8.8/udp/1234").expect("valid multiaddr"),
|
||||
]
|
||||
expectedlibp2pAddrs = @[
|
||||
MultiAddress.init("/ip4/8.8.8.8/tcp/5000").expect("valid multiaddr"),
|
||||
MultiAddress.init("/ip4/8.8.8.8/tcp/5000").expect("valid multiaddr"),
|
||||
MultiAddress.init("/ip4/8.8.8.8/tcp/5000").expect("valid multiaddr"),
|
||||
]
|
||||
expectedDiscoveryAddrs =
|
||||
@[
|
||||
MultiAddress.init("/ip4/8.8.8.8/udp/1234").expect("valid multiaddr"),
|
||||
MultiAddress.init("/ip4/8.8.8.8/udp/1234").expect("valid multiaddr"),
|
||||
MultiAddress.init("/ip4/8.8.8.8/udp/1234").expect("valid multiaddr"),
|
||||
]
|
||||
expectedlibp2pAddrs =
|
||||
@[
|
||||
MultiAddress.init("/ip4/8.8.8.8/tcp/5000").expect("valid multiaddr"),
|
||||
MultiAddress.init("/ip4/8.8.8.8/tcp/5000").expect("valid multiaddr"),
|
||||
MultiAddress.init("/ip4/8.8.8.8/tcp/5000").expect("valid multiaddr"),
|
||||
]
|
||||
|
||||
#ipv6Addr = MultiAddress.init("/ip6/::1/tcp/5000").expect("valid multiaddr")
|
||||
addrs = @[localAddr, anyAddr, publicAddr]
|
||||
@ -41,3 +43,26 @@ suite "NAT Address Tests":
|
||||
# Verify results
|
||||
check(discoveryAddrs == expectedDiscoveryAddrs)
|
||||
check(libp2pAddrs == expectedlibp2pAddrs)
|
||||
|
||||
suite "setupAddress":
|
||||
test "public bind IP with NatNone returns bind IP":
|
||||
let
|
||||
bindIp = parseIpAddress("8.8.8.8")
|
||||
natConfig = NatConfig(hasExtIp: false, nat: NatStrategy.NatNone)
|
||||
(ip, tcpPort, udpPort) =
|
||||
setupAddress(natConfig, bindIp, Port(5000), Port(5001), "test")
|
||||
|
||||
check ip == some(bindIp)
|
||||
check tcpPort == some(Port(5000))
|
||||
check udpPort == some(Port(5001))
|
||||
|
||||
test "private bind IP with NatNone returns no IP":
|
||||
let
|
||||
bindIp = parseIpAddress("192.168.1.1")
|
||||
natConfig = NatConfig(hasExtIp: false, nat: NatStrategy.NatNone)
|
||||
(ip, tcpPort, udpPort) =
|
||||
setupAddress(natConfig, bindIp, Port(5000), Port(5001), "test")
|
||||
|
||||
check ip == none(IpAddress)
|
||||
check tcpPort == some(Port(5000))
|
||||
check udpPort == some(Port(5001))
|
||||
|
||||
67
tests/storage/testnatutils.nim
Normal file
67
tests/storage/testnatutils.nim
Normal file
@ -0,0 +1,67 @@
|
||||
import std/[unittest, net, options]
|
||||
import pkg/chronos
|
||||
import ../../storage/utils/natutils
|
||||
|
||||
suite "isGlobalUnicast":
|
||||
test "localhost IPv4 is not global unicast":
|
||||
check not isGlobalUnicast(parseIpAddress("127.0.0.1"))
|
||||
|
||||
test "unspecified IPv4 is not global unicast":
|
||||
check not isGlobalUnicast(parseIpAddress("0.0.0.0"))
|
||||
|
||||
test "link-local IPv4 is not global unicast":
|
||||
check not isGlobalUnicast(parseIpAddress("169.254.1.1"))
|
||||
|
||||
test "private IPv4 is not global unicast":
|
||||
check not isGlobalUnicast(parseIpAddress("10.0.0.1"))
|
||||
|
||||
test "public IPv4 is global unicast":
|
||||
check isGlobalUnicast(parseIpAddress("8.8.8.8"))
|
||||
|
||||
test "localhost IPv6 is not global unicast":
|
||||
check not isGlobalUnicast(parseIpAddress("::1"))
|
||||
|
||||
test "unspecified IPv6 is not global unicast":
|
||||
check not isGlobalUnicast(parseIpAddress("::"))
|
||||
|
||||
test "link-local IPv6 is not global unicast":
|
||||
check not isGlobalUnicast(parseIpAddress("fe80::1"))
|
||||
|
||||
test "private IPv6 is not global unicast":
|
||||
check not isGlobalUnicast(parseIpAddress("fc00::1"))
|
||||
|
||||
test "public IPv6 is global unicast":
|
||||
check isGlobalUnicast(parseIpAddress("2606:4700::1"))
|
||||
|
||||
suite "getRoute":
|
||||
test "getRouteIpv4 returns a valid IPv4":
|
||||
let res = getRouteIpv4()
|
||||
|
||||
check res.isOk
|
||||
check res.get().family == IpAddressFamily.IPv4
|
||||
|
||||
test "getRouteIpv6 returns a valid IPv6":
|
||||
let res = getRouteIpv6()
|
||||
# If the machine does not have a global route because
|
||||
# it is not configured for IPv6, the test will fail
|
||||
# because it didn't find the best route. In that case,
|
||||
# we can just skip the test, because it is not a problem
|
||||
# with the test itself but the machine configuration.
|
||||
if res.isErr:
|
||||
check res.error == "No best route found"
|
||||
else:
|
||||
check res.get().family == IpAddressFamily.IPv6
|
||||
|
||||
suite "getBestLocalAddress":
|
||||
test "specific IPv4 is returned as it is":
|
||||
let ip = parseIpAddress("192.168.1.1")
|
||||
check getBestLocalAddress(ip) == some(ip)
|
||||
|
||||
test "specific IPv6 is returned as it is":
|
||||
let ip = parseIpAddress("2606:4700::1")
|
||||
check getBestLocalAddress(ip) == some(ip)
|
||||
|
||||
test "0.0.0.0 resolves to a local IPv4":
|
||||
let res = getBestLocalAddress(parseIpAddress("0.0.0.0"))
|
||||
check res.isSome
|
||||
check res.get().family == IpAddressFamily.IPv4
|
||||
Loading…
x
Reference in New Issue
Block a user