2025-06-27 11:16:00 +02:00

78 lines
2.6 KiB
Nim

import std/sequtils
import chronos, chronicles, libp2p/nameresolving/dnsresolver, libp2p/peerstore
import ../peer_manager/waku_peer_store, waku/waku_core/peers
type
OnOnlineStateChange* = proc(online: bool) {.gcsafe, raises: [].}
OnlineMonitor* = ref object
onOnlineStateChange: OnOnlineStateChange
dnsNameServers*: seq[IpAddress]
onlineStateObservers: seq[OnOnlineStateChange]
networkConnLoopHandle: Future[void] # node: WakuNode
peerStore: PeerStore
online: bool
proc checkInternetConnectivity(
nameServerIps: seq[IpAddress], timeout = 2.seconds
): Future[bool] {.async.} =
const DNSCheckDomain = "one.one.one.one"
let nameServers = nameServerIps.mapIt(initTAddress(it, Port(53)))
let dnsResolver = DnsResolver.new(nameServers)
# Resolve domain IP
let resolved = await dnsResolver.resolveIp(DNSCheckDomain, 0.Port, Domain.AF_UNSPEC)
if resolved.len > 0:
return true
else:
return false
proc updateOnlineState(self: OnlineMonitor) {.async.} =
if self.onlineStateObservers.len == 0:
trace "No online state observers registered, cannot notify about online state change"
return
let numConnectedPeers =
if self.peerStore.isNil():
0
else:
self.peerStore.peers().countIt(it.connectedness == Connected)
self.online =
if numConnectedPeers > 0:
true
else:
await checkInternetConnectivity(self.dnsNameServers)
for onlineStateObserver in self.onlineStateObservers:
onlineStateObserver(self.online)
proc networkConnectivityLoop(self: OnlineMonitor): Future[void] {.async.} =
## Checks periodically whether the node is online or not
## and triggers any change that depends on the network connectivity state
while true:
await self.updateOnlineState()
await sleepAsync(5.seconds)
proc startOnlineMonitor*(self: OnlineMonitor) =
self.networkConnLoopHandle = self.networkConnectivityLoop()
proc stopOnlineMonitor*(self: OnlineMonitor) {.async.} =
if not self.networkConnLoopHandle.isNil():
await self.networkConnLoopHandle.cancelAndWait()
proc setPeerStoreToOnlineMonitor*(self: OnlineMonitor, peerStore: PeerStore) =
self.peerStore = peerStore
proc addOnlineStateObserver*(self: OnlineMonitor, observer: OnOnlineStateChange) =
## Adds an observer that will be called when the online state changes
if observer notin self.onlineStateObservers:
self.onlineStateObservers.add(observer)
proc amIOnline*(self: OnlineMonitor): bool =
return self.online
proc init*(T: type OnlineMonitor, dnsNameServers: seq[IpAddress]): OnlineMonitor =
T(dnsNameServers: dnsNameServers, onlineStateObservers: @[])