diff --git a/libp2p/protocols/connectivity/autonat/service.nim b/libp2p/protocols/connectivity/autonat/service.nim index 327ec41..a06429c 100644 --- a/libp2p/protocols/connectivity/autonat/service.nim +++ b/libp2p/protocols/connectivity/autonat/service.nim @@ -82,11 +82,14 @@ proc hasEnoughIncomingSlots(switch: Switch): bool = proc doesPeerHaveIncomingConn(switch: Switch, peerId: PeerId): bool = return switch.connManager.selectMuxer(peerId, In) != nil -proc handleAnswer(self: AutonatService, ans: NetworkReachability) {.async.} = +proc handleAnswer(self: AutonatService, ans: NetworkReachability): Future[bool] {.async.} = if ans == Unknown: return + let oldNetworkReachability = self.networkReachability + let oldConfidence = self.confidence + if self.answers.len == self.maxQueueSize: self.answers.popFirst() self.answers.addLast(ans) @@ -103,6 +106,9 @@ proc handleAnswer(self: AutonatService, ans: NetworkReachability) {.async.} = debug "Current status", currentStats = $self.networkReachability, confidence = $self.confidence, answers = self.answers + # Return whether anything has changed + return self.networkReachability != oldNetworkReachability or self.confidence != oldConfidence + proc askPeer(self: AutonatService, switch: Switch, peerId: PeerId): Future[NetworkReachability] {.async.} = logScope: peerId = $peerId @@ -129,9 +135,9 @@ proc askPeer(self: AutonatService, switch: Switch, peerId: PeerId): Future[Netwo except CatchableError as error: debug "dialMe unexpected error", msg = error.msg Unknown - await self.handleAnswer(ans) - if not isNil(self.statusAndConfidenceHandler): - await self.statusAndConfidenceHandler(self.networkReachability, self.confidence) + let hasReachabilityOrConfidenceChanged = await self.handleAnswer(ans) + if hasReachabilityOrConfidenceChanged: + await self.callHandler() await switch.peerInfo.update() return ans @@ -193,7 +199,6 @@ method setup*(self: AutonatService, switch: Switch): Future[bool] {.async.} = method run*(self: AutonatService, switch: Switch) {.async, public.} = trace "Running AutonatService" await askConnectedPeers(self, switch) - await self.callHandler() method stop*(self: AutonatService, switch: Switch): Future[bool] {.async, public.} = info "Stopping AutonatService" diff --git a/libp2p/services/autorelayservice.nim b/libp2p/services/autorelayservice.nim index c1b2c52..dc1c861 100644 --- a/libp2p/services/autorelayservice.nim +++ b/libp2p/services/autorelayservice.nim @@ -32,6 +32,9 @@ type addressMapper: AddressMapper rng: ref HmacDrbgContext +proc isRunning*(self: AutoRelayService): bool = + return self.running + proc addressMapper( self: AutoRelayService, listenAddrs: seq[MultiAddress]): Future[seq[MultiAddress]] {.gcsafe, async.} = diff --git a/libp2p/services/hpservice.nim b/libp2p/services/hpservice.nim index c88c865..60c9434 100644 --- a/libp2p/services/hpservice.nim +++ b/libp2p/services/hpservice.nim @@ -105,9 +105,9 @@ method setup*(self: HPService, switch: Switch): Future[bool] {.async.} = switch.connManager.addPeerEventHandler(self.newConnectedPeerHandler, PeerEventKind.Joined) self.onNewStatusHandler = proc (networkReachability: NetworkReachability, confidence: Option[float]) {.gcsafe, async.} = - if networkReachability == NetworkReachability.NotReachable: + if networkReachability == NetworkReachability.NotReachable and not self.autoRelayService.isRunning(): discard await self.autoRelayService.setup(switch) - elif networkReachability == NetworkReachability.Reachable: + elif networkReachability == NetworkReachability.Reachable and self.autoRelayService.isRunning(): discard await self.autoRelayService.stop(switch) # We do it here instead of in the AutonatService because this is useful only when hole punching. diff --git a/tests/testautonatservice.nim b/tests/testautonatservice.nim index 5f6289f..2767771 100644 --- a/tests/testautonatservice.nim +++ b/tests/testautonatservice.nim @@ -407,7 +407,8 @@ suite "Autonat Service": # switch1 is now full, should stick to last observation awaiter = newFuture[void]() await autonatService.run(switch1) - await awaiter + + await sleepAsync(200.millis) check autonatService.networkReachability == NetworkReachability.Reachable check libp2p_autonat_reachability_confidence.value(["Reachable"]) == 1