mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-06-27 21:09:28 +00:00
Add DHT client mode
This commit is contained in:
parent
48abbe20fa
commit
641b9f0443
@ -135,15 +135,24 @@ components:
|
||||
type: object
|
||||
required:
|
||||
- reachability
|
||||
- clientMode
|
||||
- relayRunning
|
||||
- portMapping
|
||||
properties:
|
||||
reachability:
|
||||
type: string
|
||||
enum: [Unknown, Reachable, NotReachable]
|
||||
description: AutoNAT reachability status
|
||||
clientMode:
|
||||
type: boolean
|
||||
description: Whether the DHT is running in client mode (not added to remote routing tables)
|
||||
relayRunning:
|
||||
type: boolean
|
||||
description: Whether the AutoRelay service is currently running
|
||||
portMapping:
|
||||
type: string
|
||||
enum: [none, upnp, pmp]
|
||||
description: Active NAT port mapping type
|
||||
|
||||
DataList:
|
||||
type: object
|
||||
|
||||
@ -149,10 +149,12 @@ method handleNatStatus*(
|
||||
debug "AutoRelayService stopped"
|
||||
|
||||
discovery.updateRecords(@[dialBackAddr.get], discoveryPort)
|
||||
# TODO: switch DHT to server mode
|
||||
discovery.protocol.clientMode = false
|
||||
of NotReachable:
|
||||
var hasPortMapping = false
|
||||
|
||||
discovery.protocol.clientMode = true
|
||||
|
||||
if dialBackAddr.isNone:
|
||||
warn "Got empty dialback address in AutoNat when node is NotReachable"
|
||||
else:
|
||||
@ -176,6 +178,7 @@ method handleNatStatus*(
|
||||
debug "AutoRelayService stopped"
|
||||
|
||||
discovery.updateRecords(@[announceAddress], udpPort)
|
||||
discovery.protocol.clientMode = false
|
||||
hasPortMapping = true
|
||||
|
||||
if not hasPortMapping and not autoRelayService.isRunning:
|
||||
|
||||
@ -596,6 +596,7 @@ proc initDebugApi(
|
||||
$autonat.get.networkReachability
|
||||
else:
|
||||
"unknown",
|
||||
"clientMode": node.discovery.protocol.clientMode,
|
||||
"relayRunning": autoRelay.isSome and autoRelay.get.isRunning,
|
||||
"portMapping":
|
||||
if natMapper.isNone or natMapper.get.portMappingType == NoMapping:
|
||||
|
||||
@ -99,9 +99,13 @@ proc start*(s: StorageServer) {.async.} =
|
||||
]
|
||||
else:
|
||||
# Don't announce address and wait for AutoNat
|
||||
# TODO: DHT client mode
|
||||
@[]
|
||||
|
||||
if not s.config.nat.hasExtIp:
|
||||
# Nodes with autonat start with client mode.
|
||||
# It will be updated if reachable.
|
||||
s.storageNode.discovery.protocol.clientMode = true
|
||||
|
||||
s.storageNode.discovery.updateRecords(announceAddrs, s.config.discoveryPort)
|
||||
|
||||
await s.storageNode.start()
|
||||
|
||||
@ -13,28 +13,25 @@ const
|
||||
RelayTimeout = 30_000
|
||||
PollInterval = 1_000
|
||||
|
||||
proc checkNatReachability*(client: StorageClient, reachability: string) {.async.} =
|
||||
check eventuallySafe(
|
||||
(await client.natReachability()).get() == reachability,
|
||||
timeout = RelayTimeout,
|
||||
pollInterval = PollInterval,
|
||||
)
|
||||
|
||||
proc checkRelayIsRunning*(client: StorageClient, isRunning: bool) {.async.} =
|
||||
check eventuallySafe(
|
||||
(await client.natRelayRunning()).get() == isRunning,
|
||||
timeout = RelayTimeout,
|
||||
pollInterval = PollInterval,
|
||||
)
|
||||
|
||||
proc checkNatStatus*(
|
||||
client: StorageClient, reachability: string, relayRunning: bool
|
||||
) {.async.} =
|
||||
check eventuallySafe(
|
||||
block:
|
||||
let addrs = (await client.info()).get["addrs"].getElems.mapIt(it.getStr)
|
||||
addrs.anyIt("p2p-circuit" in it) == isRunning,
|
||||
let info = (await client.info()).get
|
||||
let nat = info["nat"]
|
||||
let addrs = info["addrs"].getElems.mapIt(it.getStr)
|
||||
nat["reachability"].getStr() == reachability and
|
||||
nat["clientMode"].getBool() == relayRunning and
|
||||
nat["relayRunning"].getBool() == relayRunning and
|
||||
addrs.anyIt("p2p-circuit" in it) == relayRunning,
|
||||
timeout = RelayTimeout,
|
||||
pollInterval = PollInterval,
|
||||
)
|
||||
|
||||
proc checkNatStatus*(client: StorageClient, reachability: string) {.async.} =
|
||||
await client.checkNatStatus(reachability, reachability == "NotReachable")
|
||||
|
||||
# Reminder: multinodesuite setup the first node as bootstrap node
|
||||
multinodesuite "AutoNAT detection":
|
||||
let natConfig = NodeConfigs(
|
||||
@ -48,8 +45,7 @@ multinodesuite "AutoNAT detection":
|
||||
)
|
||||
test "node is reachable when using bootstrap node on same network", natConfig:
|
||||
let node2 = clients()[1]
|
||||
await node2.client.checkNatReachability("Reachable")
|
||||
await node2.client.checkRelayIsRunning(false)
|
||||
await node2.client.checkNatStatus("Reachable")
|
||||
|
||||
let endpointIndependentConfig = NodeConfigs(
|
||||
clients: StorageConfigs
|
||||
@ -64,8 +60,7 @@ multinodesuite "AutoNAT detection":
|
||||
# EIF = Endpoint Independent Filtering
|
||||
test "node with simulated EIF nat is detected as reachable", endpointIndependentConfig:
|
||||
let node2 = clients()[1]
|
||||
await node2.client.checkNatReachability("Reachable")
|
||||
await node2.client.checkRelayIsRunning(false)
|
||||
await node2.client.checkNatStatus("Reachable")
|
||||
|
||||
let autonatConfig = NodeConfigs(
|
||||
clients: StorageConfigs
|
||||
@ -81,8 +76,7 @@ multinodesuite "AutoNAT detection":
|
||||
test "node with simulated APDF nat is detected as not reachable and starts relay",
|
||||
autonatConfig:
|
||||
let node2 = clients()[1]
|
||||
await node2.client.checkNatReachability("NotReachable")
|
||||
await node2.client.checkRelayIsRunning(true)
|
||||
await node2.client.checkNatStatus("NotReachable")
|
||||
|
||||
let transitionConfig = NodeConfigs(
|
||||
clients: StorageConfigs
|
||||
@ -100,13 +94,11 @@ multinodesuite "AutoNAT detection":
|
||||
transitionConfig:
|
||||
let node2 = clients()[1]
|
||||
|
||||
await node2.client.checkNatReachability("NotReachable")
|
||||
await node2.client.checkRelayIsRunning(true)
|
||||
await node2.client.checkNatStatus("NotReachable")
|
||||
|
||||
check (await node2.client.setNatFiltering("endpoint-independent")).isOk
|
||||
|
||||
await node2.client.checkNatReachability("Reachable")
|
||||
await node2.client.checkRelayIsRunning(false)
|
||||
await node2.client.checkNatStatus("Reachable")
|
||||
|
||||
let natToSimConfig = NodeConfigs(
|
||||
clients: StorageConfigs
|
||||
@ -123,13 +115,11 @@ multinodesuite "AutoNAT detection":
|
||||
natToSimConfig:
|
||||
let node2 = clients()[1]
|
||||
|
||||
await node2.client.checkNatReachability("Reachable")
|
||||
await node2.client.checkRelayIsRunning(false)
|
||||
await node2.client.checkNatStatus("Reachable")
|
||||
|
||||
check (await node2.client.setNatFiltering("address-and-port-dependent")).isOk
|
||||
|
||||
await node2.client.checkNatReachability("NotReachable")
|
||||
await node2.client.checkRelayIsRunning(true)
|
||||
await node2.client.checkNatStatus("NotReachable")
|
||||
|
||||
let multiNatConfig = NodeConfigs(
|
||||
clients: StorageConfigs
|
||||
@ -148,7 +138,5 @@ multinodesuite "AutoNAT detection":
|
||||
let node2 = clients()[1]
|
||||
let node3 = clients()[2]
|
||||
|
||||
await node2.client.checkNatReachability("NotReachable")
|
||||
await node3.client.checkNatReachability("NotReachable")
|
||||
await node2.client.checkRelayIsRunning(true)
|
||||
await node3.client.checkRelayIsRunning(true)
|
||||
await node2.client.checkNatStatus("NotReachable")
|
||||
await node3.client.checkNatStatus("NotReachable")
|
||||
|
||||
@ -8,7 +8,7 @@ import ../storageclient
|
||||
import ../storageconfig
|
||||
import ../../../storage/utils/natutils
|
||||
|
||||
from ./testnat.nim import checkNatReachability, checkRelayIsRunning
|
||||
from ./testnat.nim import checkNatStatus
|
||||
|
||||
const
|
||||
DetectionTimeout = 15_000
|
||||
@ -39,7 +39,8 @@ multinodesuite "AutoNAT UPnP port mapping":
|
||||
|
||||
let node2 = clients()[1]
|
||||
|
||||
await node2.client.checkNatReachability("NotReachable")
|
||||
let isRelayRunning = false
|
||||
await node2.client.checkNatStatus("NotReachable", isRelayRunning)
|
||||
|
||||
check eventuallySafe(
|
||||
block:
|
||||
@ -51,7 +52,8 @@ multinodesuite "AutoNAT UPnP port mapping":
|
||||
|
||||
# Ideally we should find a way to test that the node is Reachable now
|
||||
|
||||
await node2.client.checkRelayIsRunning(false)
|
||||
let isRelayRunning = false
|
||||
await node2.client.checkNatStatus("NotReachable", isRelayRunning)
|
||||
|
||||
# Extract mapped TCP port from announce addresses and verify it exists on the IGD
|
||||
let announceAddrs =
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import std/json
|
||||
import std/sequtils
|
||||
import pkg/chronos
|
||||
import pkg/questionable/results
|
||||
|
||||
|
||||
@ -271,17 +271,6 @@ proc connectPeer*(
|
||||
let response = await client.get(url)
|
||||
assert response.status == 200
|
||||
|
||||
proc natReachability*(
|
||||
client: StorageClient
|
||||
): Future[?!string] {.async: (raises: [CancelledError, HttpError]).} =
|
||||
let info = await client.info()
|
||||
if info.isErr:
|
||||
return failure "Failed to get node info"
|
||||
try:
|
||||
return info.get()["nat"]["reachability"].getStr().success
|
||||
except KeyError as e:
|
||||
return failure e.msg
|
||||
|
||||
proc natRelayRunning*(
|
||||
client: StorageClient
|
||||
): Future[?!bool] {.async: (raises: [CancelledError, HttpError]).} =
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import std/[net, importutils, envvars]
|
||||
import std/[net, importutils]
|
||||
import pkg/chronos
|
||||
import pkg/libp2p/[multiaddress, multihash, multicodec]
|
||||
import pkg/libp2p/protocols/connectivity/autonat/types
|
||||
@ -95,6 +95,7 @@ asyncchecksuite "NAT - handleNatStatus":
|
||||
check disc.announceAddrs ==
|
||||
@[MultiAddress.init("/ip4/1.2.3.4/tcp/9000").expect("valid")]
|
||||
check not autoRelay.isRunning
|
||||
check not disc.protocol.clientMode
|
||||
|
||||
test "handleNatStatus starts autoRelay when NotReachable and UPnP failed":
|
||||
let mapper = MockNatMapper(mappedPorts: none((Port, Port)))
|
||||
@ -104,6 +105,7 @@ asyncchecksuite "NAT - handleNatStatus":
|
||||
)
|
||||
|
||||
check autoRelay.isRunning
|
||||
check disc.protocol.clientMode
|
||||
|
||||
test "handleNatStatus starts autoRelay when NotReachable and mapping fails":
|
||||
let dialBack = MultiAddress.init("/ip4/1.2.3.4/tcp/8080").expect("valid")
|
||||
@ -115,6 +117,7 @@ asyncchecksuite "NAT - handleNatStatus":
|
||||
|
||||
check autoRelay.isRunning
|
||||
check disc.announceAddrs == newSeq[MultiAddress]()
|
||||
check disc.protocol.clientMode
|
||||
|
||||
test "handleNatStatus does not announce address when Reachable and no dialBackAddr":
|
||||
let mapper = MockNatMapper(mappedPorts: none((Port, Port)))
|
||||
@ -125,6 +128,7 @@ asyncchecksuite "NAT - handleNatStatus":
|
||||
|
||||
check disc.announceAddrs == newSeq[MultiAddress]()
|
||||
check not autoRelay.isRunning
|
||||
check not disc.protocol.clientMode
|
||||
|
||||
test "handleNatStatus stops relay and announces dialBackAddr when Reachable":
|
||||
let dialBack = MultiAddress.init("/ip4/1.2.3.4/tcp/8080").expect("valid")
|
||||
@ -137,3 +141,4 @@ asyncchecksuite "NAT - handleNatStatus":
|
||||
|
||||
check not autoRelay.isRunning
|
||||
check disc.announceAddrs == @[dialBack]
|
||||
check not disc.protocol.clientMode
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user