mirror of
https://github.com/vacp2p/nim-libp2p.git
synced 2026-01-09 02:38:19 -05:00
chore(autonat-v2): add utils (#1657)
This commit is contained in:
@@ -85,6 +85,7 @@ when defined(libp2p_autotls_support):
|
||||
../crypto/rsa,
|
||||
../utils/heartbeat,
|
||||
../transports/transport,
|
||||
../utils/ipaddr,
|
||||
../transports/tcptransport,
|
||||
../nameresolving/dnsresolver
|
||||
|
||||
@@ -150,7 +151,10 @@ when defined(libp2p_autotls_support):
|
||||
if self.config.ipAddress.isNone():
|
||||
try:
|
||||
self.config.ipAddress = Opt.some(getPublicIPAddress())
|
||||
except AutoTLSError as exc:
|
||||
except ValueError as exc:
|
||||
error "Failed to get public IP address", err = exc.msg
|
||||
return false
|
||||
except OSError as exc:
|
||||
error "Failed to get public IP address", err = exc.msg
|
||||
return false
|
||||
self.managerFut = self.run(switch)
|
||||
|
||||
@@ -22,7 +22,7 @@ const
|
||||
type AutoTLSError* = object of LPError
|
||||
|
||||
when defined(libp2p_autotls_support):
|
||||
import net, strutils
|
||||
import strutils
|
||||
from times import DateTime, toTime, toUnix
|
||||
import stew/base36
|
||||
import
|
||||
@@ -33,36 +33,6 @@ when defined(libp2p_autotls_support):
|
||||
../nameresolving/nameresolver,
|
||||
./acme/client
|
||||
|
||||
proc checkedGetPrimaryIPAddr*(): IpAddress {.raises: [AutoTLSError].} =
|
||||
# This is so that we don't need to catch Exceptions directly
|
||||
# since we support 1.6.16 and getPrimaryIPAddr before nim 2 didn't have explicit .raises. pragmas
|
||||
try:
|
||||
return getPrimaryIPAddr()
|
||||
except Exception as exc:
|
||||
raise newException(AutoTLSError, "Error while getting primary IP address", exc)
|
||||
|
||||
proc isIPv4*(ip: IpAddress): bool =
|
||||
ip.family == IpAddressFamily.IPv4
|
||||
|
||||
proc isPublic*(ip: IpAddress): bool {.raises: [AutoTLSError].} =
|
||||
let ip = $ip
|
||||
try:
|
||||
not (
|
||||
ip.startsWith("10.") or
|
||||
(ip.startsWith("172.") and parseInt(ip.split(".")[1]) in 16 .. 31) or
|
||||
ip.startsWith("192.168.") or ip.startsWith("127.") or ip.startsWith("169.254.")
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise newException(AutoTLSError, "Failed to parse IP address", exc)
|
||||
|
||||
proc getPublicIPAddress*(): IpAddress {.raises: [AutoTLSError].} =
|
||||
let ip = checkedGetPrimaryIPAddr()
|
||||
if not ip.isIPv4():
|
||||
raise newException(AutoTLSError, "Host does not have an IPv4 address")
|
||||
if not ip.isPublic():
|
||||
raise newException(AutoTLSError, "Host does not have a public IPv4 address")
|
||||
return ip
|
||||
|
||||
proc asMoment*(dt: DateTime): Moment =
|
||||
let unixTime: int64 = dt.toTime.toUnix
|
||||
return Moment.init(unixTime, Second)
|
||||
|
||||
@@ -843,6 +843,14 @@ proc init*(
|
||||
res.data.finish()
|
||||
ok(res)
|
||||
|
||||
proc getPart*(ma: MultiAddress, codec: MultiCodec): MaResult[MultiAddress] =
|
||||
## Returns the first multiaddress in ``value`` with codec ``codec``
|
||||
for part in ma:
|
||||
let part = ?part
|
||||
if codec == ?part.protoCode:
|
||||
return ok(part)
|
||||
err("no such codec in multiaddress")
|
||||
|
||||
proc getProtocol(name: string): MAProtocol {.inline.} =
|
||||
let mc = MultiCodec.codec(name)
|
||||
if mc != InvalidMultiCodec:
|
||||
@@ -1119,3 +1127,32 @@ proc getRepeatedField*(
|
||||
err(ProtoError.IncorrectBlob)
|
||||
else:
|
||||
ok(true)
|
||||
|
||||
proc areAddrsConsistent*(a, b: MultiAddress): bool =
|
||||
## Checks if two multiaddresses have the same protocol stack.
|
||||
let protosA = a.protocols().get()
|
||||
let protosB = b.protocols().get()
|
||||
if protosA.len != protosB.len:
|
||||
return false
|
||||
|
||||
for idx in 0 ..< protosA.len:
|
||||
let protoA = protosA[idx]
|
||||
let protoB = protosB[idx]
|
||||
|
||||
if protoA != protoB:
|
||||
if idx == 0:
|
||||
# allow DNS ↔ IP at the first component
|
||||
if protoB == multiCodec("dns") or protoB == multiCodec("dnsaddr"):
|
||||
if not (protoA == multiCodec("ip4") or protoA == multiCodec("ip6")):
|
||||
return false
|
||||
elif protoB == multiCodec("dns4"):
|
||||
if protoA != multiCodec("ip4"):
|
||||
return false
|
||||
elif protoB == multiCodec("dns6"):
|
||||
if protoA != multiCodec("ip6"):
|
||||
return false
|
||||
else:
|
||||
return false
|
||||
else:
|
||||
return false
|
||||
true
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
import results
|
||||
import chronos, chronicles
|
||||
import ../../../switch, ../../../multiaddress, ../../../peerid
|
||||
import core
|
||||
import types
|
||||
|
||||
logScope:
|
||||
topics = "libp2p autonat"
|
||||
|
||||
@@ -20,9 +20,9 @@ import
|
||||
../../../peerid,
|
||||
../../../utils/[semaphore, future],
|
||||
../../../errors
|
||||
import core
|
||||
import types
|
||||
|
||||
export core
|
||||
export types
|
||||
|
||||
logScope:
|
||||
topics = "libp2p autonat"
|
||||
|
||||
@@ -14,11 +14,11 @@ import chronos, metrics
|
||||
import ../../../switch
|
||||
import ../../../wire
|
||||
import client
|
||||
from core import NetworkReachability, AutonatUnreachableError
|
||||
from types import NetworkReachability, AutonatUnreachableError
|
||||
import ../../../utils/heartbeat
|
||||
import ../../../crypto/crypto
|
||||
|
||||
export core.NetworkReachability
|
||||
export NetworkReachability
|
||||
|
||||
logScope:
|
||||
topics = "libp2p autonatservice"
|
||||
|
||||
@@ -10,25 +10,35 @@
|
||||
{.push raises: [].}
|
||||
|
||||
import results, chronos, chronicles
|
||||
import ../../../multiaddress, ../../../peerid #, ../../../errors
|
||||
import ../../../protobuf/minprotobuf
|
||||
|
||||
logScope:
|
||||
topics = "libp2p autonat v2"
|
||||
|
||||
const
|
||||
AutonatV2DialRequestCodec* = "/libp2p/autonat/2/dial-request"
|
||||
AutonatV2DialBackCodec* = "/libp2p/autonat/2/dial-back"
|
||||
import
|
||||
../../../multiaddress, ../../../peerid, ../../../protobuf/minprotobuf, ../../../switch
|
||||
from ../autonat/types import NetworkReachability
|
||||
|
||||
type
|
||||
# DialBack and DialBackResponse are not defined as AutonatV2Msg as per the spec
|
||||
# likely because they are expected in response to some other message
|
||||
AutonatV2Codec* {.pure.} = enum
|
||||
DialRequest = "/libp2p/autonat/2/dial-request"
|
||||
DialBack = "/libp2p/autonat/2/dial-back"
|
||||
|
||||
AutonatV2Response* = object
|
||||
reachability*: NetworkReachability
|
||||
dialResp*: DialResponse
|
||||
addrs*: Opt[MultiAddress]
|
||||
|
||||
AutonatV2Error* = object of LPError
|
||||
|
||||
Nonce* = uint64
|
||||
|
||||
AddrIdx* = uint32
|
||||
|
||||
NumBytes* = uint64
|
||||
|
||||
MsgType* {.pure.} = enum
|
||||
Unused = 0 # nim requires the first variant to be zero
|
||||
DialRequest = 1
|
||||
DialResponse = 2
|
||||
DialDataRequest = 3
|
||||
DialDataResponse = 4
|
||||
# DialBack and DialBackResponse are not defined as AutonatV2Msg as per the spec
|
||||
# likely because they are expected in response to some other message
|
||||
DialRequest
|
||||
DialResponse
|
||||
DialDataRequest
|
||||
DialDataResponse
|
||||
|
||||
ResponseStatus* {.pure.} = enum
|
||||
EInternalError = 0
|
||||
@@ -47,30 +57,28 @@ type
|
||||
|
||||
DialRequest* = object
|
||||
addrs*: seq[MultiAddress]
|
||||
nonce*: uint64
|
||||
nonce*: Nonce
|
||||
|
||||
DialResponse* = object
|
||||
status*: ResponseStatus
|
||||
addrIdx*: Opt[uint32]
|
||||
addrIdx*: Opt[AddrIdx]
|
||||
dialStatus*: Opt[DialStatus]
|
||||
|
||||
DialBack* = object
|
||||
nonce*: uint64
|
||||
nonce*: Nonce
|
||||
|
||||
DialBackResponse* = object
|
||||
status*: DialBackStatus
|
||||
|
||||
DialDataRequest* = object
|
||||
addrIdx*: uint32
|
||||
numBytes*: uint64
|
||||
addrIdx*: AddrIdx
|
||||
numBytes*: NumBytes
|
||||
|
||||
DialDataResponse* = object
|
||||
data*: seq[byte]
|
||||
|
||||
AutonatV2Msg* = object
|
||||
case msgType*: MsgType
|
||||
of MsgType.Unused:
|
||||
discard
|
||||
of MsgType.DialRequest:
|
||||
dialReq*: DialRequest
|
||||
of MsgType.DialResponse:
|
||||
@@ -92,7 +100,7 @@ proc encode*(dialReq: DialRequest): ProtoBuffer =
|
||||
proc decode*(T: typedesc[DialRequest], pb: ProtoBuffer): Opt[T] =
|
||||
var
|
||||
addrs: seq[MultiAddress]
|
||||
nonce: uint64
|
||||
nonce: Nonce
|
||||
if not ?pb.getRepeatedField(1, addrs).toOpt():
|
||||
return Opt.none(T)
|
||||
if not ?pb.getField(2, nonce).toOpt():
|
||||
@@ -114,13 +122,13 @@ proc encode*(dialResp: DialResponse): ProtoBuffer =
|
||||
proc decode*(T: typedesc[DialResponse], pb: ProtoBuffer): Opt[T] =
|
||||
var
|
||||
status: uint
|
||||
addrIdx: uint32
|
||||
addrIdx: AddrIdx
|
||||
dialStatus: uint
|
||||
|
||||
if not ?pb.getField(1, status).toOpt():
|
||||
return Opt.none(T)
|
||||
|
||||
var optAddrIdx = Opt.none(uint32)
|
||||
var optAddrIdx = Opt.none(AddrIdx)
|
||||
if ?pb.getField(2, addrIdx).toOpt():
|
||||
optAddrIdx = Opt.some(addrIdx)
|
||||
|
||||
@@ -144,7 +152,7 @@ proc encode*(dialBack: DialBack): ProtoBuffer =
|
||||
encoded
|
||||
|
||||
proc decode*(T: typedesc[DialBack], pb: ProtoBuffer): Opt[T] =
|
||||
var nonce: uint64
|
||||
var nonce: Nonce
|
||||
if not ?pb.getField(1, nonce).toOpt():
|
||||
return Opt.none(T)
|
||||
Opt.some(T(nonce: nonce))
|
||||
@@ -172,8 +180,8 @@ proc encode*(dialDataReq: DialDataRequest): ProtoBuffer =
|
||||
|
||||
proc decode*(T: typedesc[DialDataRequest], pb: ProtoBuffer): Opt[T] =
|
||||
var
|
||||
addrIdx: uint32
|
||||
numBytes: uint64
|
||||
addrIdx: AddrIdx
|
||||
numBytes: NumBytes
|
||||
if not ?pb.getField(1, addrIdx).toOpt():
|
||||
return Opt.none(T)
|
||||
if not ?pb.getField(2, numBytes).toOpt():
|
||||
@@ -193,20 +201,25 @@ proc decode*(T: typedesc[DialDataResponse], pb: ProtoBuffer): Opt[T] =
|
||||
return Opt.none(T)
|
||||
Opt.some(T(data: data))
|
||||
|
||||
proc protoField(msgType: MsgType): int =
|
||||
case msgType
|
||||
of MsgType.DialRequest: 1.int
|
||||
of MsgType.DialResponse: 2.int
|
||||
of MsgType.DialDataRequest: 3.int
|
||||
of MsgType.DialDataResponse: 4.int
|
||||
|
||||
# AutonatV2Msg
|
||||
proc encode*(msg: AutonatV2Msg): ProtoBuffer =
|
||||
var encoded = initProtoBuffer()
|
||||
case msg.msgType
|
||||
of MsgType.Unused:
|
||||
doAssert false, "invalid enum variant: Unused"
|
||||
of MsgType.DialRequest:
|
||||
encoded.write(MsgType.DialRequest.int, msg.dialReq.encode())
|
||||
encoded.write(MsgType.DialRequest.protoField, msg.dialReq.encode())
|
||||
of MsgType.DialResponse:
|
||||
encoded.write(MsgType.DialResponse.int, msg.dialResp.encode())
|
||||
encoded.write(MsgType.DialResponse.protoField, msg.dialResp.encode())
|
||||
of MsgType.DialDataRequest:
|
||||
encoded.write(MsgType.DialDataRequest.int, msg.dialDataReq.encode())
|
||||
encoded.write(MsgType.DialDataRequest.protoField, msg.dialDataReq.encode())
|
||||
of MsgType.DialDataResponse:
|
||||
encoded.write(MsgType.DialDataResponse.int, msg.dialDataResp.encode())
|
||||
encoded.write(MsgType.DialDataResponse.protoField, msg.dialDataResp.encode())
|
||||
encoded.finish()
|
||||
encoded
|
||||
|
||||
@@ -215,19 +228,19 @@ proc decode*(T: typedesc[AutonatV2Msg], pb: ProtoBuffer): Opt[T] =
|
||||
msgTypeOrd: uint32
|
||||
msg: ProtoBuffer
|
||||
|
||||
if ?pb.getField(MsgType.DialRequest.int, msg).toOpt():
|
||||
if ?pb.getField(MsgType.DialRequest.protoField, msg).toOpt():
|
||||
let dialReq = DialRequest.decode(msg).valueOr:
|
||||
return Opt.none(AutonatV2Msg)
|
||||
Opt.some(AutonatV2Msg(msgType: MsgType.DialRequest, dialReq: dialReq))
|
||||
elif ?pb.getField(MsgType.DialResponse.int, msg).toOpt():
|
||||
elif ?pb.getField(MsgType.DialResponse.protoField, msg).toOpt():
|
||||
let dialResp = DialResponse.decode(msg).valueOr:
|
||||
return Opt.none(AutonatV2Msg)
|
||||
Opt.some(AutonatV2Msg(msgType: MsgType.DialResponse, dialResp: dialResp))
|
||||
elif ?pb.getField(MsgType.DialDataRequest.int, msg).toOpt():
|
||||
elif ?pb.getField(MsgType.DialDataRequest.protoField, msg).toOpt():
|
||||
let dialDataReq = DialDataRequest.decode(msg).valueOr:
|
||||
return Opt.none(AutonatV2Msg)
|
||||
Opt.some(AutonatV2Msg(msgType: MsgType.DialDataRequest, dialDataReq: dialDataReq))
|
||||
elif ?pb.getField(MsgType.DialDataResponse.int, msg).toOpt():
|
||||
elif ?pb.getField(MsgType.DialDataResponse.protoField, msg).toOpt():
|
||||
let dialDataResp = DialDataResponse.decode(msg).valueOr:
|
||||
return Opt.none(AutonatV2Msg)
|
||||
Opt.some(
|
||||
|
||||
47
libp2p/protocols/connectivity/autonatv2/utils.nim
Normal file
47
libp2p/protocols/connectivity/autonatv2/utils.nim
Normal file
@@ -0,0 +1,47 @@
|
||||
{.push raises: [].}
|
||||
|
||||
import results
|
||||
import chronos
|
||||
import
|
||||
../../protocol,
|
||||
../../../switch,
|
||||
../../../multiaddress,
|
||||
../../../multicodec,
|
||||
../../../peerid,
|
||||
../../../protobuf/minprotobuf,
|
||||
../autonat/service,
|
||||
./types
|
||||
|
||||
proc asNetworkReachability*(self: DialResponse): NetworkReachability =
|
||||
if self.status == EInternalError:
|
||||
return Unknown
|
||||
if self.status == ERequestRejected:
|
||||
return Unknown
|
||||
if self.status == EDialRefused:
|
||||
return Unknown
|
||||
|
||||
# if got here it means a dial was attempted
|
||||
let dialStatus = self.dialStatus.valueOr:
|
||||
return Unknown
|
||||
if dialStatus == Unused:
|
||||
return Unknown
|
||||
if dialStatus == EDialError:
|
||||
return NotReachable
|
||||
if dialStatus == EDialBackError:
|
||||
return NotReachable
|
||||
return Reachable
|
||||
|
||||
proc asAutonatV2Response*(
|
||||
self: DialResponse, testAddrs: seq[MultiAddress]
|
||||
): AutonatV2Response =
|
||||
let addrIdx = self.addrIdx.valueOr:
|
||||
return AutonatV2Response(
|
||||
reachability: self.asNetworkReachability(),
|
||||
dialResp: self,
|
||||
addrs: Opt.none(MultiAddress),
|
||||
)
|
||||
AutonatV2Response(
|
||||
reachability: self.asNetworkReachability(),
|
||||
dialResp: self,
|
||||
addrs: Opt.some(testAddrs[addrIdx]),
|
||||
)
|
||||
@@ -18,9 +18,9 @@ import
|
||||
../multicodec,
|
||||
../muxers/muxer,
|
||||
../upgrademngrs/upgrade,
|
||||
../protocols/connectivity/autonat/core
|
||||
../protocols/connectivity/autonat/types
|
||||
|
||||
export core.NetworkReachability
|
||||
export types.NetworkReachability
|
||||
|
||||
logScope:
|
||||
topics = "libp2p transport"
|
||||
|
||||
74
libp2p/utils/ipaddr.nim
Normal file
74
libp2p/utils/ipaddr.nim
Normal file
@@ -0,0 +1,74 @@
|
||||
import net, strutils
|
||||
|
||||
import ../switch, ../multiaddress, ../multicodec
|
||||
|
||||
proc isIPv4*(ip: IpAddress): bool =
|
||||
ip.family == IpAddressFamily.IPv4
|
||||
|
||||
proc isIPv6*(ip: IpAddress): bool =
|
||||
ip.family == IpAddressFamily.IPv6
|
||||
|
||||
proc isPrivate*(ip: string): bool {.raises: [ValueError].} =
|
||||
ip.startsWith("10.") or
|
||||
(ip.startsWith("172.") and parseInt(ip.split(".")[1]) in 16 .. 31) or
|
||||
ip.startsWith("192.168.") or ip.startsWith("127.") or ip.startsWith("169.254.")
|
||||
|
||||
proc isPrivate*(ip: IpAddress): bool {.raises: [ValueError].} =
|
||||
isPrivate($ip)
|
||||
|
||||
proc isPublic*(ip: string): bool {.raises: [ValueError].} =
|
||||
not isPrivate(ip)
|
||||
|
||||
proc isPublic*(ip: IpAddress): bool {.raises: [ValueError].} =
|
||||
isPublic($ip)
|
||||
|
||||
proc getPublicIPAddress*(): IpAddress {.raises: [OSError, ValueError].} =
|
||||
let ip =
|
||||
try:
|
||||
getPrimaryIPAddr()
|
||||
except OSError as exc:
|
||||
raise exc
|
||||
except ValueError as exc:
|
||||
raise exc
|
||||
except Exception as exc:
|
||||
raise newException(OSError, "Could not get primary IP address")
|
||||
if not ip.isIPv4():
|
||||
raise newException(ValueError, "Host does not have an IPv4 address")
|
||||
if not ip.isPublic():
|
||||
raise newException(ValueError, "Host does not have a public IPv4 address")
|
||||
ip
|
||||
|
||||
proc ipAddrMatches*(
|
||||
lookup: MultiAddress, addrs: seq[MultiAddress], ip4: bool = true
|
||||
): bool =
|
||||
## Checks ``lookup``'s IP is in any of addrs
|
||||
|
||||
let ipType =
|
||||
if ip4:
|
||||
multiCodec("ip4")
|
||||
else:
|
||||
multiCodec("ip6")
|
||||
|
||||
let lookup = lookup.getPart(ipType).valueOr:
|
||||
return false
|
||||
|
||||
for ma in addrs:
|
||||
ma[0].withValue(ipAddr):
|
||||
if ipAddr == lookup:
|
||||
return true
|
||||
false
|
||||
|
||||
proc ipSupport*(addrs: seq[MultiAddress]): (bool, bool) =
|
||||
## Returns ipv4 and ipv6 support status of a list of MultiAddresses
|
||||
|
||||
var ipv4 = false
|
||||
var ipv6 = false
|
||||
|
||||
for ma in addrs:
|
||||
ma[0].withValue(addrIp):
|
||||
if IP4.match(addrIp):
|
||||
ipv4 = true
|
||||
elif IP6.match(addrIp):
|
||||
ipv6 = true
|
||||
|
||||
(ipv4, ipv6)
|
||||
@@ -14,7 +14,7 @@
|
||||
import chronos
|
||||
import
|
||||
../../libp2p/[protocols/connectivity/autonat/client, peerid, multiaddress, switch]
|
||||
from ../../libp2p/protocols/connectivity/autonat/core import
|
||||
from ../../libp2p/protocols/connectivity/autonat/types import
|
||||
NetworkReachability, AutonatUnreachableError, AutonatError
|
||||
|
||||
type
|
||||
|
||||
@@ -13,12 +13,12 @@ import std/options
|
||||
import chronos
|
||||
import
|
||||
../libp2p/[
|
||||
switch,
|
||||
transports/tcptransport,
|
||||
upgrademngrs/upgrade,
|
||||
builders,
|
||||
protocols/connectivity/autonatv2/types,
|
||||
# nameresolving/nameresolver,
|
||||
# nameresolving/mockresolver,
|
||||
protocols/connectivity/autonatv2/utils,
|
||||
],
|
||||
./helpers
|
||||
|
||||
@@ -107,3 +107,45 @@ suite "AutonatV2":
|
||||
|
||||
# DialBackResponse
|
||||
checkEncodeDecode(DialBackResponse(status: DialBackStatus.Ok))
|
||||
|
||||
asyncTest "asNetworkReachability":
|
||||
check asNetworkReachability(DialResponse(status: EInternalError)) == Unknown
|
||||
check asNetworkReachability(DialResponse(status: ERequestRejected)) == Unknown
|
||||
check asNetworkReachability(DialResponse(status: EDialRefused)) == Unknown
|
||||
check asNetworkReachability(
|
||||
DialResponse(status: ResponseStatus.Ok, dialStatus: Opt.none(DialStatus))
|
||||
) == Unknown
|
||||
check asNetworkReachability(
|
||||
DialResponse(status: ResponseStatus.Ok, dialStatus: Opt.some(Unused))
|
||||
) == Unknown
|
||||
check asNetworkReachability(
|
||||
DialResponse(status: ResponseStatus.Ok, dialStatus: Opt.some(EDialError))
|
||||
) == NotReachable
|
||||
check asNetworkReachability(
|
||||
DialResponse(status: ResponseStatus.Ok, dialStatus: Opt.some(EDialBackError))
|
||||
) == NotReachable
|
||||
check asNetworkReachability(
|
||||
DialResponse(status: ResponseStatus.Ok, dialStatus: Opt.some(DialStatus.Ok))
|
||||
) == Reachable
|
||||
|
||||
asyncTest "asAutonatV2Response":
|
||||
let addrs = @[MultiAddress.init("/ip4/127.0.0.1/tcp/4000").get()]
|
||||
let errorDialResp = DialResponse(
|
||||
status: ResponseStatus.Ok,
|
||||
addrIdx: Opt.none(AddrIdx),
|
||||
dialStatus: Opt.none(DialStatus),
|
||||
)
|
||||
check asAutonatV2Response(errorDialResp, addrs) ==
|
||||
AutonatV2Response(
|
||||
reachability: Unknown, dialResp: errorDialResp, addrs: Opt.none(MultiAddress)
|
||||
)
|
||||
|
||||
let correctDialResp = DialResponse(
|
||||
status: ResponseStatus.Ok,
|
||||
addrIdx: Opt.some(0.AddrIdx),
|
||||
dialStatus: Opt.some(DialStatus.Ok),
|
||||
)
|
||||
check asAutonatV2Response(correctDialResp, addrs) ==
|
||||
AutonatV2Response(
|
||||
reachability: Reachable, dialResp: correctDialResp, addrs: Opt.some(addrs[0])
|
||||
)
|
||||
|
||||
@@ -14,7 +14,7 @@ import unittest2
|
||||
|
||||
import ../libp2p/protocols/connectivity/dcutr/core as dcore
|
||||
import ../libp2p/protocols/connectivity/dcutr/[client, server]
|
||||
from ../libp2p/protocols/connectivity/autonat/core import NetworkReachability
|
||||
from ../libp2p/protocols/connectivity/autonat/types import NetworkReachability
|
||||
import ../libp2p/builders
|
||||
import ../libp2p/utils/future
|
||||
import ./helpers
|
||||
|
||||
55
tests/testipaddr.nim
Normal file
55
tests/testipaddr.nim
Normal file
@@ -0,0 +1,55 @@
|
||||
{.used.}
|
||||
|
||||
# Nim-Libp2p
|
||||
# Copyright (c) 2025 Status Research & Development GmbH
|
||||
# Licensed under either of
|
||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
||||
# at your option.
|
||||
# This file may not be copied, modified, or distributed except according to
|
||||
# those terms.
|
||||
|
||||
import std/options
|
||||
import chronos
|
||||
import ../libp2p/[utils/ipaddr], ./helpers
|
||||
|
||||
suite "IpAddr Utils":
|
||||
teardown:
|
||||
checkTrackers()
|
||||
|
||||
test "ipAddrMatches":
|
||||
# same ip address
|
||||
check ipAddrMatches(
|
||||
MultiAddress.init("/ip4/127.0.0.1/tcp/4041").get(),
|
||||
@[MultiAddress.init("/ip4/127.0.0.1/tcp/4040").get()],
|
||||
)
|
||||
# different ip address
|
||||
check not ipAddrMatches(
|
||||
MultiAddress.init("/ip4/127.0.0.2/tcp/4041").get(),
|
||||
@[MultiAddress.init("/ip4/127.0.0.1/tcp/4040").get()],
|
||||
)
|
||||
|
||||
test "ipSupport":
|
||||
check ipSupport(@[MultiAddress.init("/ip4/127.0.0.1/tcp/4040").get()]) ==
|
||||
(true, false)
|
||||
check ipSupport(@[MultiAddress.init("/ip6/::1/tcp/4040").get()]) == (false, true)
|
||||
check ipSupport(
|
||||
@[
|
||||
MultiAddress.init("/ip6/::1/tcp/4040").get(),
|
||||
MultiAddress.init("/ip4/127.0.0.1/tcp/4040").get(),
|
||||
]
|
||||
) == (true, true)
|
||||
|
||||
test "isPrivate, isPublic":
|
||||
check isPrivate("192.168.1.100")
|
||||
check not isPublic("192.168.1.100")
|
||||
check isPrivate("10.0.0.25")
|
||||
check not isPublic("10.0.0.25")
|
||||
check isPrivate("169.254.12.34")
|
||||
check not isPublic("169.254.12.34")
|
||||
check isPrivate("172.31.200.8")
|
||||
check not isPublic("172.31.200.8")
|
||||
check not isPrivate("1.1.1.1")
|
||||
check isPublic("1.1.1.1")
|
||||
check not isPrivate("185.199.108.153")
|
||||
check isPublic("185.199.108.153")
|
||||
@@ -341,6 +341,20 @@ suite "MultiAddress test suite":
|
||||
MultiAddress.init("/ip4/0.0.0.0").get().protoAddress().get() == address_v4
|
||||
MultiAddress.init("/ip6/::0").get().protoAddress().get() == address_v6
|
||||
|
||||
test "MultiAddress getPart":
|
||||
let ma = MultiAddress
|
||||
.init(
|
||||
"/ip4/0.0.0.0/tcp/0/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC/p2p-circuit/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSuNEXT/unix/stdio/"
|
||||
)
|
||||
.get()
|
||||
check:
|
||||
$ma.getPart(multiCodec("ip4")).get() == "/ip4/0.0.0.0"
|
||||
$ma.getPart(multiCodec("tcp")).get() == "/tcp/0"
|
||||
# returns first codec match
|
||||
$ma.getPart(multiCodec("p2p")).get() ==
|
||||
"/p2p/QmcgpsyWgH8Y8ajJz1Cu72KnS5uo2Aa2LpzU7kinSupNKC"
|
||||
ma.getPart(multiCodec("udp")).isErr()
|
||||
|
||||
test "MultiAddress getParts":
|
||||
let ma = MultiAddress
|
||||
.init(
|
||||
@@ -421,3 +435,22 @@ suite "MultiAddress test suite":
|
||||
for item in CrashesVectors:
|
||||
let res = MultiAddress.init(hexToSeqByte(item))
|
||||
check res.isErr()
|
||||
|
||||
test "areAddrsConsistent":
|
||||
# same address should be consistent
|
||||
check areAddrsConsistent(
|
||||
MultiAddress.init("/ip4/127.0.0.1/tcp/4040").get(),
|
||||
MultiAddress.init("/ip4/127.0.0.1/tcp/4040").get(),
|
||||
)
|
||||
|
||||
# different addresses with same stack should be consistent
|
||||
check areAddrsConsistent(
|
||||
MultiAddress.init("/ip4/127.0.0.2/tcp/4041").get(),
|
||||
MultiAddress.init("/ip4/127.0.0.1/tcp/4040").get(),
|
||||
)
|
||||
|
||||
# addresses with different stacks should not be consistent
|
||||
check not areAddrsConsistent(
|
||||
MultiAddress.init("/ip4/127.0.0.1/tcp/4040").get(),
|
||||
MultiAddress.init("/ip4/127.0.0.1/udp/4040").get(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user