66 lines
2.4 KiB
Nim

import std/algorithm
import std/json
import std/sequtils
import pkg/chronos
import pkg/questionable/results
import ./multinodes
import ./storageclient
import ./storageconfig
const
RelayTimeout* = 30_000
PollInterval* = 1_000
NatScheduleInterval* = 5.seconds
proc checkNatStatus*(
client: StorageClient, reachability: string, relayRunning: bool, clientMode: bool
) {.async.} =
check eventuallySafe(
block:
let info = (await client.info()).get
let nat = info["nat"]
let addrs = info["addrs"].getElems.mapIt(it.getStr)
let r = nat["reachability"].getStr()
let cm = nat["clientMode"].getBool()
let rr = nat["relayRunning"].getBool()
let ha = addrs.anyIt("p2p-circuit" in it)
let pm = nat["portMapping"].getStr()
let aa = info["announceAddresses"].getElems.mapIt(it.getStr)
# Reachable nodes must announce their dialable (non-circuit) addrs to
# the DHT (peerInfo observer); relayed nodes must announce their
# circuit addrs (onReservation).
let announceOk =
if reachability == "Reachable":
aa.len > 0 and aa.sorted == addrs.filterIt("p2p-circuit" notin it).sorted
elif relayRunning:
aa.len > 0 and aa.allIt("p2p-circuit" in it)
else:
true
# It is important to check all the conditions together to avoid race
# (new autonat iteration)
# So we add a checkoint for better debug in case of failures
checkpoint(
"reachability=" & r & " (want " & reachability & ")" & " clientMode=" & $cm &
" (want " & $clientMode & ")" & " relayRunning=" & $rr & " (want " &
$relayRunning & ")" & " p2p-circuit=" & $ha & " (want " & $relayRunning & ")" &
" portMapping=" & pm & " announceAddresses=" & $aa
)
r == reachability and cm == clientMode and rr == relayRunning and
ha == relayRunning and announceOk,
timeout = RelayTimeout,
pollInterval = PollInterval,
)
proc checkReachable*(client: StorageClient) {.async.} =
await client.checkNatStatus("Reachable", relayRunning = false, clientMode = false)
# Relay might be false when the mapping has been created for UPnP / TCP but
# Autonat didn't detect yet Reachable
proc checkNotReachable*(client: StorageClient, relayRunning = true) {.async.} =
await client.checkNatStatus(
"NotReachable", relayRunning = relayRunning, clientMode = true
)