Skip to content

Commit

Permalink
handle dns addrs
Browse files Browse the repository at this point in the history
  • Loading branch information
diegomrsantos committed May 16, 2023
1 parent a1eb53b commit 6e7df5b
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 7 deletions.
1 change: 1 addition & 0 deletions libp2p/services/autorelayservice.nim
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ proc reserveAndUpdate(self: AutoRelayService, relayPid: PeerId, switch: Switch)
if relayPid notin self.relayAddresses or self.relayAddresses[relayPid] != relayedAddr:
self.relayAddresses[relayPid] = relayedAddr
await switch.peerInfo.update()
debug "Updated relay addresses", relayPid, relayedAddr
if not self.onReservation.isNil():
self.onReservation(concat(toSeq(self.relayAddresses.values)))
await sleepAsync chronos.seconds(ttl - 30)
Expand Down
17 changes: 12 additions & 5 deletions libp2p/services/hpservice.nim
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,21 @@ proc new*(T: typedesc[HPService], autonatService: AutonatService, autoRelayServi
return T(autonatService: autonatService, autoRelayService: autoRelayService, isPublicIPAddrProc: isPublicIPAddrProc)

proc tryStartingDirectConn(self: HPService, switch: Switch, peerId: PeerId): Future[bool] {.async.} =
proc tryConnect(address: MultiAddress): Future[bool] {.async.} =
debug "Trying to create direct connection to ", peerId, " at ", address
await switch.connect(peerId, @[address], true, false)
debug "Direct connection created."
return true

await sleepAsync(500.milliseconds) # wait for AddressBook to be populated
for address in switch.peerStore[AddressBook][peerId]:
try:
let ta = initTAddress(address)
if ta.isOk() and self.isPublicIPAddrProc(ta.get()):
await switch.connect(peerId, @[address], true, false)
debug "Direct connection created."
return true
if DNS.matchPartial(address):
return await tryConnect(address)
else:
let ta = initTAddress(address)
if ta.isOk() and self.isPublicIPAddrProc(ta.get()):
return await tryConnect(address)
except CatchableError as err:
debug "Failed to create direct connection.", err = err.msg
continue
Expand Down
2 changes: 1 addition & 1 deletion libp2p/switch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ proc start*(s: Switch) {.async, gcsafe, public.} =
warn "Switch has already been started"
return

trace "starting switch for peer", peerInfo = s.peerInfo
debug "starting switch for peer", peerInfo = s.peerInfo
var startFuts: seq[Future[void]]
for t in s.transports:
let addrs = s.peerInfo.listenAddrs.filterIt(
Expand Down
53 changes: 52 additions & 1 deletion tests/testhpservice.nim
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ import ../libp2p/[builders,
import ../libp2p/protocols/connectivity/relay/[relay, client]
import ../libp2p/protocols/connectivity/autonat/[service]
import ../libp2p/wire
import ../libp2p/nameresolving/nameresolver
import ../libp2p/nameresolving/mockresolver

import stubs/autonatclientstub

proc isPublicAddrIPAddrMock(ta: TransportAddress): bool =
return true

proc createSwitch(r: Relay = nil, hpService: Service = nil): Switch {.raises: [LPError, Defect].} =
proc createSwitch(r: Relay = nil, hpService: Service = nil, nameResolver: NameResolver = nil): Switch {.raises: [LPError, Defect].} =
var builder = SwitchBuilder.new()
.withRng(newRng())
.withAddresses(@[ MultiAddress.init("/ip4/0.0.0.0/tcp/0").tryGet() ])
Expand All @@ -46,6 +49,9 @@ proc createSwitch(r: Relay = nil, hpService: Service = nil): Switch {.raises: [L
if r != nil:
builder = builder.withCircuitRelay(r)

if nameResolver != nil:
builder = builder.withNameResolver(nameResolver)

return builder.build()

proc buildRelayMA(switchRelay: Switch, switchClient: Switch): MultiAddress =
Expand Down Expand Up @@ -90,6 +96,51 @@ suite "Hole Punching":
await allFuturesThrowing(
privatePeerSwitch.stop(), publicPeerSwitch.stop(), switchRelay.stop())

asyncTest "Direct connection must work when peer address is public and dns is used":

let autonatClientStub = AutonatClientStub.new(expectedDials = 1)
autonatClientStub.answer = NotReachable
let autonatService = AutonatService.new(autonatClientStub, newRng(), maxQueueSize = 1)

let relayClient = RelayClient.new()
let privatePeerRelayAddr = newFuture[seq[MultiAddress]]()


let resolver = MockResolver.new()
resolver.ipResponses[("localhost", false)] = @["127.0.0.1"]
resolver.ipResponses[("localhost", true)] = @["::1"]

let publicPeerSwitch = createSwitch(RelayClient.new(), nameResolver = resolver)

proc addressMapper(listenAddrs: seq[MultiAddress]): Future[seq[MultiAddress]] {.gcsafe, async.} =
return @[MultiAddress.init("/dns4/localhost/").tryGet() & listenAddrs[0][1].tryGet()]
publicPeerSwitch.peerInfo.addressMappers.add(addressMapper)
await publicPeerSwitch.peerInfo.update()

proc checkMA(address: seq[MultiAddress]) =
if not privatePeerRelayAddr.completed():
privatePeerRelayAddr.complete(address)

let autoRelayService = AutoRelayService.new(1, relayClient, checkMA, newRng())

let hpservice = HPService.new(autonatService, autoRelayService, isPublicAddrIPAddrMock)

let privatePeerSwitch = createSwitch(relayClient, hpservice, nameResolver = resolver)
let switchRelay = createSwitch(Relay.new())

await allFutures(switchRelay.start(), privatePeerSwitch.start(), publicPeerSwitch.start())

await privatePeerSwitch.connect(switchRelay.peerInfo.peerId, switchRelay.peerInfo.addrs)

await publicPeerSwitch.connect(privatePeerSwitch.peerInfo.peerId, (await privatePeerRelayAddr))

checkExpiring:
privatePeerSwitch.connManager.connCount(publicPeerSwitch.peerInfo.peerId) == 1 and
not isRelayed(privatePeerSwitch.connManager.selectMuxer(publicPeerSwitch.peerInfo.peerId).connection)

await allFuturesThrowing(
privatePeerSwitch.stop(), publicPeerSwitch.stop(), switchRelay.stop())

proc holePunchingTest(connectStub: proc (): Future[void] {.async.},
isPublicIPAddrProc: IsPublicIPAddrProc,
answer: Answer) {.async.} =
Expand Down

0 comments on commit 6e7df5b

Please sign in to comment.