From d1a44ef997cb6d94212ca39c89a15de6f0ab3e21 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Fri, 5 Jun 2026 18:06:10 +0400 Subject: [PATCH] Prevent libplum re-initialization after shutdown --- storage/nat.nim | 11 ++++++++++- storage/storage.nim | 2 +- tests/storage/testnat.nim | 15 +++++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/storage/nat.nim b/storage/nat.nim index 5a12b675..24a3c902 100644 --- a/storage/nat.nim +++ b/storage/nat.nim @@ -47,13 +47,14 @@ type NatPortMapper* = ref object of RootObj activeTcpPort*: Option[Port] activeUdpPort*: Option[Port] plumInitialized: bool + closed: bool method mapNatPorts*( m: NatPortMapper ): Future[Option[(Port, Port, MappingProtocol)]] {. async: (raises: [CancelledError]), base, gcsafe .} = - if m.natConfig.hasExtIp: + if m.closed or m.natConfig.hasExtIp: return none((Port, Port, MappingProtocol)) # If both mappings are still active, return the stored ports without recreating. @@ -126,6 +127,11 @@ proc close*(m: NatPortMapper) = discard cleanup() m.plumInitialized = false +proc stop*(m: NatPortMapper) = + ## Ensure that any future AutoNAT callback does not re-initialize libplum. + m.closed = true + m.close() + proc isPortMapped*(m: NatPortMapper, port: Port): bool = m.activeTcpPort.isSome and m.activeTcpPort.get == port @@ -170,6 +176,9 @@ method handleNatStatus*( switch: Switch, autoRelayService: AutoRelayService, ) {.async: (raises: [CancelledError]), base, gcsafe.} = + if m.closed: + return + case networkReachability of Unknown: discard diff --git a/storage/storage.nim b/storage/storage.nim index e2479bdd..c23cbac6 100644 --- a/storage/storage.nim +++ b/storage/storage.nim @@ -158,7 +158,7 @@ proc stop*(s: StorageServer) {.async.} = notice "Stopping Storage node" if s.natMapper.isSome: - s.natMapper.get.close() + s.natMapper.get.stop() if s.holePunchHandler.isSome: s.storageNode.switch.removePeerEventHandler( diff --git a/tests/storage/testnat.nim b/tests/storage/testnat.nim index 8dd87b1e..9b367fa5 100644 --- a/tests/storage/testnat.nim +++ b/tests/storage/testnat.nim @@ -114,6 +114,21 @@ asyncchecksuite "NAT - handleNatStatus": check not autoRelay.isRunning check not disc.protocol.clientMode + test "handleNatStatus does nothing after the mapper is stopped": + let dialBack = MultiAddress.init("/ip4/1.2.3.4/tcp/8080").expect("valid") + let mapper = MockNatPortMapper( + mappedPorts: some((Port(9000), Port(9001), MappingProtocol.UPnP)) + ) + mapper.stop() + + autorelayservice.setup(autoRelay, sw) + await mapper.handleNatStatus( + NotReachable, Opt.some(dialBack), discoveryPort, disc, sw, autoRelay + ) + + check not autoRelay.isRunning + check disc.announceAddrs == newSeq[MultiAddress]() + test "announcePeerInfoAddrs excludes relay circuit addresses": let circuitAddr = MultiAddress .init("/ip4/1.2.3.4/tcp/4040/p2p/" & $sw.peerInfo.peerId & "/p2p-circuit")