Autonat integration and reachability info in debug api

This commit is contained in:
Arnaud 2026-04-10 18:28:21 +04:00
parent 8110abcb9d
commit 4d9eb9c34a
No known key found for this signature in database
GPG Key ID: A6C7C781817146FA
2 changed files with 58 additions and 9 deletions

View File

@ -23,6 +23,7 @@ import pkg/confutils
import pkg/libp2p
import pkg/libp2p/routing_record
import pkg/libp2p/protocols/connectivity/autonat/service
import pkg/codexdht/discv5/spr as spr
import ../logutils
@ -557,7 +558,12 @@ proc initNodeApi(node: StorageNodeRef, conf: StorageConf, router: var RestRouter
return
RestApiResponse.error(Http500, "Unknown error dialling peer", headers = headers)
proc initDebugApi(node: StorageNodeRef, conf: StorageConf, router: var RestRouter) =
proc initDebugApi(
node: StorageNodeRef,
conf: StorageConf,
autonat: AutonatService,
router: var RestRouter,
) =
let allowedOrigin = router.allowedOrigin
router.api(MethodGet, "/api/storage/v1/debug/info") do() -> RestApiResponse:
@ -577,6 +583,7 @@ proc initDebugApi(node: StorageNodeRef, conf: StorageConf, router: var RestRoute
"announceAddresses": node.discovery.announceAddrs,
"table": table,
"storage": {"version": $storageVersion, "revision": $storageRevision},
"nat": {"reachability": $autonat.networkReachability},
}
# return pretty json for human readability
@ -637,12 +644,13 @@ proc initRestApi*(
node: StorageNodeRef,
conf: StorageConf,
repoStore: RepoStore,
autonat: AutonatService,
corsAllowedOrigin: ?string,
): RestRouter =
var router = RestRouter.init(validate, corsAllowedOrigin)
initDataApi(node, repoStore, router)
initNodeApi(node, conf, router)
initDebugApi(node, conf, router)
initDebugApi(node, conf, autonat, router)
return router

View File

@ -17,6 +17,7 @@ import pkg/chronos
import pkg/taskpools
import pkg/presto
import pkg/libp2p
import pkg/libp2p/protocols/connectivity/autonat/[service, client]
import pkg/confutils
import pkg/confutils/defs
import pkg/stew/io2
@ -51,6 +52,7 @@ type
repoStore: RepoStore
maintenance: BlockMaintainer
taskpool: Taskpool
autonatService*: AutonatService
isStarted: bool
StoragePrivateKey* = libp2p.PrivateKey # alias
@ -76,9 +78,25 @@ proc start*(s: StorageServer) {.async.} =
await s.storageNode.switch.start()
let (announceAddrs, discoveryAddrs) = nattedAddress(
s.config.nat, s.storageNode.switch.peerInfo.addrs, s.config.discoveryPort
)
let announceIp =
if s.config.nat.hasExtIp:
some(s.config.nat.extIp)
else:
getBestLocalAddress(s.config.listenIp)
if announceIp.isNone:
# We should have an IP, even at private IP
raise newException(StorageError, "Unable to determine an IP address to announce")
# Remap switch addresses to the resolved IP (replaces 0.0.0.0 or :: with the actual address),
# keeping unique entries only.
let announceAddrs = s.storageNode.switch.peerInfo.addrs
.mapIt(it.remapAddr(ip = announceIp, port = none(Port)))
.deduplicate()
let discoveryAddrs =
@[getMultiAddrWithIPAndUDPPort(announceIp.get, s.config.discoveryPort)]
s.storageNode.discovery.updateDhtRecord(discoveryAddrs)
s.storageNode.discovery.updateAnnounceRecord(announceAddrs)
var hasPublicAddr = false
for announceAddr in announceAddrs:
@ -90,9 +108,6 @@ proc start*(s: StorageServer) {.async.} =
if not hasPublicAddr:
warn "Unable to determine a public IP address. This node will only be reachable on a private network."
s.storageNode.discovery.updateAnnounceRecord(announceAddrs)
s.storageNode.discovery.updateDhtRecord(discoveryAddrs)
await s.storageNode.start()
if s.restServer != nil:
@ -171,6 +186,16 @@ proc new*(
## create StorageServer including setting up datastore, repostore, etc
let listenMultiAddr = getMultiAddrWithIpAndTcpPort(config.listenIp, config.listenPort)
let autonatService = AutonatService.new(
autonatClient = AutonatClient.new(),
rng = random.Rng.instance(),
scheduleInterval = Opt.some(config.natScheduleInterval),
askNewConnectedPeers = true,
numPeersToAsk = config.natNumPeersToAsk,
maxQueueSize = config.natMaxQueueSize,
minConfidence = config.natMinConfidence,
)
let switch = SwitchBuilder
.new()
.withPrivateKey(privateKey)
@ -182,6 +207,8 @@ proc new*(
.withAgentVersion(config.agentString)
.withSignedPeerRecord(true)
.withTcpTransport({ServerFlags.ReuseAddr, ServerFlags.TcpNoDelay})
.withAutonat()
.withServices(@[Service(autonatService)])
.build()
var
@ -290,7 +317,9 @@ proc new*(
if config.apiBindAddress.isSome:
restServer = RestServerRef
.new(
storageNode.initRestApi(config, repoStore, config.apiCorsAllowedOrigin),
storageNode.initRestApi(
config, repoStore, autonatService, config.apiCorsAllowedOrigin
),
initTAddress(config.apiBindAddress.get(), config.apiPort),
bufferSize = (1024 * 64),
maxRequestBodySize = int.high,
@ -300,6 +329,17 @@ proc new*(
switch.mount(network)
switch.mount(manifestProto)
autonatService.statusAndConfidenceHandler(
proc(
networkReachability: NetworkReachability, confidence: Opt[float]
) {.async: (raises: [CancelledError]).} =
if networkReachability == NotReachable:
let (announceAddrs, discoveryAddrs) =
nattedAddress(config.nat, switch.peerInfo.addrs, config.discoveryPort)
discovery.updateAnnounceRecord(announceAddrs)
discovery.updateDhtRecord(discoveryAddrs)
)
StorageServer(
config: config,
storageNode: storageNode,
@ -308,4 +348,5 @@ proc new*(
maintenance: maintenance,
taskPool: taskPool,
logFile: logFile,
autonatService: autonatService,
)