Skip to content

Commit

Permalink
fix: support ipv6 dual stack (#1148)
Browse files Browse the repository at this point in the history
Fixes #1147
  • Loading branch information
diegomrsantos authored Jul 10, 2024
1 parent 86563cb commit fa19bbb
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 49 deletions.
57 changes: 27 additions & 30 deletions libp2p/services/wildcardresolverservice.nim
Original file line number Diff line number Diff line change
Expand Up @@ -97,52 +97,49 @@ proc getWildcardMultiAddresses(

proc getWildcardAddress(
maddress: MultiAddress,
multiCodec: MultiCodec,
anyAddr: openArray[uint8],
addrFamily: AddressFamily,
port: Port,
networkInterfaceProvider: NetworkInterfaceProvider,
): seq[MultiAddress] =
var addresses: seq[MultiAddress]
maddress.getProtocolArgument(multiCodec).withValue(address):
if address == anyAddr:
let filteredInterfaceAddresses = networkInterfaceProvider(addrFamily)
addresses.add(
getWildcardMultiAddresses(filteredInterfaceAddresses, IPPROTO_TCP, port)
)
else:
addresses.add(maddress)
return addresses
let filteredInterfaceAddresses = networkInterfaceProvider(addrFamily)
getWildcardMultiAddresses(filteredInterfaceAddresses, IPPROTO_TCP, port)

proc expandWildcardAddresses(
networkInterfaceProvider: NetworkInterfaceProvider, listenAddrs: seq[MultiAddress]
): seq[MultiAddress] =
var addresses: seq[MultiAddress]

# In this loop we expand bound addresses like `0.0.0.0` and `::` to list of interface addresses.
for listenAddr in listenAddrs:
if TCP_IP.matchPartial(listenAddr):
listenAddr.getProtocolArgument(multiCodec("tcp")).withValue(portArg):
let port = Port(uint16.fromBytesBE(portArg))
if IP4.matchPartial(listenAddr):
let wildcardAddresses = getWildcardAddress(
listenAddr,
multiCodec("ip4"),
AnyAddress.address_v4,
AddressFamily.IPv4,
port,
networkInterfaceProvider,
)
addresses.add(wildcardAddresses)
listenAddr.getProtocolArgument(multiCodec("ip4")).withValue(ip4):
if ip4 == AnyAddress.address_v4:
addresses.add(
getWildcardAddress(
listenAddr, AddressFamily.IPv4, port, networkInterfaceProvider
)
)
else:
addresses.add(listenAddr)
elif IP6.matchPartial(listenAddr):
let wildcardAddresses = getWildcardAddress(
listenAddr,
multiCodec("ip6"),
AnyAddress6.address_v6,
AddressFamily.IPv6,
port,
networkInterfaceProvider,
)
addresses.add(wildcardAddresses)
listenAddr.getProtocolArgument(multiCodec("ip6")).withValue(ip6):
if ip6 == AnyAddress6.address_v6:
addresses.add(
getWildcardAddress(
listenAddr, AddressFamily.IPv6, port, networkInterfaceProvider
)
)
# IPv6 dual stack
addresses.add(
getWildcardAddress(
listenAddr, AddressFamily.IPv4, port, networkInterfaceProvider
)
)
else:
addresses.add(listenAddr)
else:
addresses.add(listenAddr)
else:
Expand Down
3 changes: 2 additions & 1 deletion tests/testnative.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@ import
testbufferstream, testidentify, testobservedaddrmanager, testconnmngr, testswitch,
testnoise, testpeerinfo, testpeerstore, testping, testmplex, testrelayv1, testrelayv2,
testrendezvous, testdiscovery, testyamux, testautonat, testautonatservice,
testautorelay, testdcutr, testhpservice, testutility, testhelpers
testautorelay, testdcutr, testhpservice, testutility, testhelpers,
testwildcardresolverservice
32 changes: 14 additions & 18 deletions tests/testwildcardresolverservice.nim
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,11 @@ proc getAddressesMock(
echo "Error: " & $e.msg
fail()

proc createSwitch(svc: Service): Switch =
proc createSwitch(svc: Service, addrs: seq[MultiAddress]): Switch =
SwitchBuilder
.new()
.withRng(newRng())
.withAddresses(
@[
MultiAddress.init("/ip4/127.0.0.1/tcp/0/").tryGet(),
MultiAddress.init("/ip4/0.0.0.0/tcp/0/").tryGet(),
MultiAddress.init("/ip6/::/tcp/0/").tryGet(),
],
false,
)
.withAddresses(addrs, false)
.withTcpTransport()
.withMplex()
.withNoise()
Expand All @@ -63,26 +56,29 @@ suite "WildcardAddressResolverService":
asyncTest "WildcardAddressResolverService must resolve wildcard addresses and stop doing so when stopped":
let svc: Service =
WildcardAddressResolverService.new(networkInterfaceProvider = getAddressesMock)
let switch = createSwitch(svc)
let switch = createSwitch(
svc,
@[
MultiAddress.init("/ip4/127.0.0.1/tcp/0/").tryGet(),
MultiAddress.init("/ip4/0.0.0.0/tcp/0/").tryGet(),
MultiAddress.init("/ip6/::/tcp/0/").tryGet(),
],
)
await switch.start()
let tcpIp4Locahost = switch.peerInfo.addrs[0][multiCodec("tcp")].get
let tcpIp4Wildcard = switch.peerInfo.addrs[1][multiCodec("tcp")].get
let tcpIp6 = switch.peerInfo.addrs[2][multiCodec("tcp")].get # tcp port for ip6
let tcpIp6 = switch.peerInfo.addrs[3][multiCodec("tcp")].get # tcp port for ip6

check switch.peerInfo.addrs ==
@[
MultiAddress.init("/ip4/127.0.0.1" & $tcpIp4Locahost).get,
MultiAddress.init("/ip4/0.0.0.0" & $tcpIp4Wildcard).get,
MultiAddress.init("/ip6/::" & $tcpIp6).get,
]
await svc.run(switch)
check switch.peerInfo.addrs ==
@[
MultiAddress.init("/ip4/127.0.0.1" & $tcpIp4Locahost).get,
MultiAddress.init("/ip4/127.0.0.1" & $tcpIp4Wildcard).get,
MultiAddress.init("/ip4/192.168.1.22" & $tcpIp4Wildcard).get,
MultiAddress.init("/ip6/::1" & $tcpIp6).get,
MultiAddress.init("/ip6/fe80::1" & $tcpIp6).get,
# IPv6 dual stack
MultiAddress.init("/ip4/127.0.0.1" & $tcpIp6).get,
MultiAddress.init("/ip4/192.168.1.22" & $tcpIp6).get,
]
await switch.stop()
check switch.peerInfo.addrs ==
Expand Down

0 comments on commit fa19bbb

Please sign in to comment.