Announce the mapped external UDP port instead of the discovery port

This commit is contained in:
Arnaud 2026-06-05 17:41:24 +04:00
parent 6e730658e6
commit ccb80ac79b
No known key found for this signature in database
GPG Key ID: A6C7C781817146FA
3 changed files with 32 additions and 6 deletions

View File

@ -140,7 +140,10 @@ proc announcePeerInfoAddrs*(discovery: Discovery, peerInfo: PeerInfo, udpPort: P
discovery.updateRecordsAndSpr(addrs, udpPort = udpPort)
proc setupPeerInfoObserver*(
switch: Switch, autonat: AutonatV2Service, discovery: Discovery, udpPort: Port
switch: Switch,
autonat: AutonatV2Service,
discovery: Discovery,
natMapper: NatPortMapper,
): PeerInfoObserver =
## AutoNAT's address mapper resolves peerInfo.addrs into public addresses
## once the node is Reachable; peerInfo.update() then notifies observers.
@ -150,6 +153,9 @@ proc setupPeerInfoObserver*(
addrs = peerInfo.addrs, reachability = autonat.networkReachability
if autonat.networkReachability != NetworkReachability.Reachable:
return
# When a NAT mapping is active, announce its external UDP port: the router
# may have assigned a different port than the requested discoveryPort.
let udpPort = natMapper.activeUdpPort.get(natMapper.discoveryPort)
announcePeerInfoAddrs(discovery, peerInfo, udpPort)
switch.peerInfo.addObserver(observer)

View File

@ -490,9 +490,8 @@ proc new*(
if natRouter.isSome:
natRouter.get.natMapper = natMapper
peerInfoObserver = some(
setupPeerInfoObserver(switch, autonatService.get, discovery, config.discoveryPort)
)
peerInfoObserver =
some(setupPeerInfoObserver(switch, autonatService.get, discovery, natMapper.get))
autonatService.get.setStatusAndConfidenceHandler(
proc(

View File

@ -135,7 +135,9 @@ asyncchecksuite "NAT - handleNatStatus":
test "peerInfo observer announces addresses when Reachable":
let autonat = AutonatV2Service.new(Rng.instance())
discard setupPeerInfoObserver(sw, autonat, disc, discoveryPort)
discard setupPeerInfoObserver(
sw, autonat, disc, NatPortMapper(discoveryPort: discoveryPort)
)
autonat.networkReachability = Reachable
sw.peerInfo.listenAddrs.add(
@ -145,9 +147,28 @@ asyncchecksuite "NAT - handleNatStatus":
check disc.announceAddrs == sw.peerInfo.addrs
test "peerInfo observer announces the mapped external UDP port when a mapping is active":
let autonat = AutonatV2Service.new(Rng.instance())
let mapper =
NatPortMapper(discoveryPort: discoveryPort, activeUdpPort: some(Port(40001)))
discard setupPeerInfoObserver(sw, autonat, disc, mapper)
autonat.networkReachability = Reachable
sw.peerInfo.listenAddrs.add(
MultiAddress.init("/ip4/1.2.3.4/tcp/9999").expect("valid")
)
await sw.peerInfo.update()
let sprAddrs = disc.getSpr().data.addresses.mapIt(it.address)
check MultiAddress.init("/ip4/1.2.3.4/udp/40001").expect("valid") in sprAddrs
check MultiAddress.init("/ip4/1.2.3.4/udp/" & $discoveryPort).expect("valid") notin
sprAddrs
test "peerInfo observer does not announce when the node is not Reachable":
let autonat = AutonatV2Service.new(Rng.instance())
discard setupPeerInfoObserver(sw, autonat, disc, discoveryPort)
discard setupPeerInfoObserver(
sw, autonat, disc, NatPortMapper(discoveryPort: discoveryPort)
)
autonat.networkReachability = NotReachable
sw.peerInfo.listenAddrs.add(