mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-07-24 18:43:18 +00:00
Update imports
This commit is contained in:
parent
da91a720b8
commit
affe4e2c00
@ -16,7 +16,7 @@ import
|
|||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
import pkg/chronicles
|
import pkg/chronicles
|
||||||
import pkg/libp2p
|
import pkg/libp2p
|
||||||
import pkg/libp2p/protocols/connectivity/autonat/types
|
import pkg/libp2p/protocols/connectivity/autonatv2/service
|
||||||
import pkg/libp2p/services/autorelayservice
|
import pkg/libp2p/services/autorelayservice
|
||||||
|
|
||||||
import ./utils
|
import ./utils
|
||||||
@ -58,7 +58,7 @@ logScope:
|
|||||||
type NatMapper* = ref object of RootObj
|
type NatMapper* = ref object of RootObj
|
||||||
|
|
||||||
method mapNatPorts*(m: NatMapper): Option[(Port, Port)] {.base, gcsafe, raises: [].} =
|
method mapNatPorts*(m: NatMapper): Option[(Port, Port)] {.base, gcsafe, raises: [].} =
|
||||||
raiseAssert "mapNatPorts not implemented"
|
none((Port, Port))
|
||||||
|
|
||||||
type DefaultNatMapper* = ref object of NatMapper
|
type DefaultNatMapper* = ref object of NatMapper
|
||||||
natConfig*: NatConfig
|
natConfig*: NatConfig
|
||||||
@ -303,18 +303,13 @@ proc findReachableNodes*(bootstrapNodes: seq[SignedPeerRecord]): seq[SignedPeerR
|
|||||||
|
|
||||||
proc nattedPorts*(natConfig: NatConfig, tcpPort, udpPort: Port): Option[(Port, Port)] =
|
proc nattedPorts*(natConfig: NatConfig, tcpPort, udpPort: Port): Option[(Port, Port)] =
|
||||||
if natConfig.hasExtIp:
|
if natConfig.hasExtIp:
|
||||||
return none((Port, Port)) # manual setup, no port mapping needed
|
return none((Port, Port))
|
||||||
setupNat(natConfig.nat, tcpPort, udpPort, "storage")
|
let clientId = "storage"
|
||||||
|
return setupNat(natConfig.nat, tcpPort, udpPort, clientId)
|
||||||
|
|
||||||
method mapNatPorts*(m: DefaultNatMapper): Option[(Port, Port)] {.gcsafe, raises: [].} =
|
method mapNatPorts*(m: DefaultNatMapper): Option[(Port, Port)] {.gcsafe, raises: [].} =
|
||||||
nattedPorts(m.natConfig, m.tcpPort, m.discoveryPort)
|
nattedPorts(m.natConfig, m.tcpPort, m.discoveryPort)
|
||||||
|
|
||||||
proc hasPublicIp*(addrs: seq[MultiAddress]): bool =
|
|
||||||
for addr in addrs:
|
|
||||||
let (ip, _) = getAddressAndPort(addr)
|
|
||||||
if ip.isSome and isGlobalUnicast(ip.get):
|
|
||||||
return true
|
|
||||||
|
|
||||||
proc handleNatStatus*(
|
proc handleNatStatus*(
|
||||||
networkReachability: NetworkReachability,
|
networkReachability: NetworkReachability,
|
||||||
dialBackAddr: Opt[MultiAddress],
|
dialBackAddr: Opt[MultiAddress],
|
||||||
@ -340,18 +335,20 @@ proc handleNatStatus*(
|
|||||||
let discAddr =
|
let discAddr =
|
||||||
dialBackAddr.get.remapAddr(protocol = some("udp"), port = some(discoveryPort))
|
dialBackAddr.get.remapAddr(protocol = some("udp"), port = some(discoveryPort))
|
||||||
discovery.updateAnnounceRecord(@[dialBackAddr.get])
|
discovery.updateAnnounceRecord(@[dialBackAddr.get])
|
||||||
discovery.updateDhtRecord(@[dialBackAddr.get, discAddr])
|
discovery.updateDhtRecord(@[discAddr])
|
||||||
# TODO: switch DHT to server mode
|
# TODO: switch DHT to server mode
|
||||||
of NotReachable:
|
of NotReachable:
|
||||||
var hasPortMapping = false
|
var hasPortMapping = false
|
||||||
|
|
||||||
if dialBackAddr.isSome:
|
if dialBackAddr.isNone:
|
||||||
|
warn "Got empty dialback address in AutoNat when node is Reachable"
|
||||||
|
else:
|
||||||
let maybePorts = mapper.mapNatPorts()
|
let maybePorts = mapper.mapNatPorts()
|
||||||
|
|
||||||
if maybePorts.isSome:
|
if maybePorts.isSome:
|
||||||
let (tcpPort, udpPort) = maybePorts.get()
|
let (tcpPort, udpPort) = maybePorts.get()
|
||||||
let announceAddr = dialBackAddr.get.remapAddr(port = some(tcpPort))
|
let announceAddress = dialBackAddr.get.remapAddr(port = some(tcpPort))
|
||||||
let discAddr =
|
let discoveryAddrs =
|
||||||
dialBackAddr.get.remapAddr(protocol = some("udp"), port = some(udpPort))
|
dialBackAddr.get.remapAddr(protocol = some("udp"), port = some(udpPort))
|
||||||
|
|
||||||
# TODO: Try a dial me to make sure we are reachable
|
# TODO: Try a dial me to make sure we are reachable
|
||||||
@ -360,8 +357,8 @@ proc handleNatStatus*(
|
|||||||
if not await autoRelayService.stop(switch):
|
if not await autoRelayService.stop(switch):
|
||||||
debug "AutoRelayService stop method returned false"
|
debug "AutoRelayService stop method returned false"
|
||||||
|
|
||||||
discovery.updateAnnounceRecord(@[announceAddr])
|
discovery.updateAnnounceRecord(@[announceAddress])
|
||||||
discovery.updateDhtRecord(@[announceAddr, discAddr])
|
discovery.updateDhtRecord(@[discoveryAddrs])
|
||||||
|
|
||||||
hasPortMapping = true
|
hasPortMapping = true
|
||||||
|
|
||||||
|
|||||||
@ -41,7 +41,6 @@ import ./namespaces
|
|||||||
import ./storagetypes
|
import ./storagetypes
|
||||||
import ./logutils
|
import ./logutils
|
||||||
import ./nat
|
import ./nat
|
||||||
import ./utils/natutils
|
|
||||||
|
|
||||||
logScope:
|
logScope:
|
||||||
topics = "storage node"
|
topics = "storage node"
|
||||||
@ -88,29 +87,16 @@ proc start*(s: StorageServer) {.async.} =
|
|||||||
else:
|
else:
|
||||||
getBestLocalAddress(s.config.listenIp)
|
getBestLocalAddress(s.config.listenIp)
|
||||||
|
|
||||||
if announceIp.isNone:
|
if announceIp.isSome:
|
||||||
# We should have an IP, even at private IP
|
let ip = announceIp.get
|
||||||
raise newException(StorageError, "Unable to determine an IP address to announce")
|
let announceAddrs = s.storageNode.switch.peerInfo.addrs
|
||||||
|
.mapIt(it.remapAddr(ip = some(ip), port = none(Port)))
|
||||||
# Remap switch addresses to the resolved IP (replaces 0.0.0.0 or :: with the actual address),
|
.deduplicate()
|
||||||
# keeping unique entries only.
|
let discAddr = getMultiAddrWithIPAndUDPPort(ip, s.config.discoveryPort)
|
||||||
let announceAddrs = s.storageNode.switch.peerInfo.addrs
|
s.storageNode.discovery.updateAnnounceRecord(announceAddrs)
|
||||||
.mapIt(it.remapAddr(ip = announceIp, port = none(Port)))
|
s.storageNode.discovery.updateDhtRecord(announceAddrs & @[discAddr])
|
||||||
.deduplicate()
|
else:
|
||||||
let discoveryAddrs =
|
warn "Unable to determine a local IP address to announce"
|
||||||
@[getMultiAddrWithIPAndUDPPort(announceIp.get, s.config.discoveryPort)]
|
|
||||||
s.storageNode.discovery.updateDhtRecord(announceAddrs & discoveryAddrs)
|
|
||||||
s.storageNode.discovery.updateAnnounceRecord(announceAddrs)
|
|
||||||
|
|
||||||
var hasPublicAddr = false
|
|
||||||
for announceAddr in announceAddrs:
|
|
||||||
let (maybeIp, _) = getAddressAndPort(announceAddr)
|
|
||||||
if maybeIp.isSome and maybeIp.get.isGlobalUnicast():
|
|
||||||
hasPublicAddr = true
|
|
||||||
break
|
|
||||||
|
|
||||||
if not hasPublicAddr:
|
|
||||||
warn "Unable to determine a public IP address. This node will only be reachable on a private network."
|
|
||||||
|
|
||||||
await s.storageNode.start()
|
await s.storageNode.start()
|
||||||
|
|
||||||
|
|||||||
@ -74,38 +74,3 @@ proc getMultiAddrWithIpAndTcpPort*(ip: IpAddress, port: Port): MultiAddress =
|
|||||||
return MultiAddress.init(ipFamily & $ip & "/tcp/" & $port).expect(
|
return MultiAddress.init(ipFamily & $ip & "/tcp/" & $port).expect(
|
||||||
"Failed to construct multiaddress with IP and TCP port"
|
"Failed to construct multiaddress with IP and TCP port"
|
||||||
)
|
)
|
||||||
|
|
||||||
proc getAddressAndPort*(
|
|
||||||
ma: MultiAddress
|
|
||||||
): tuple[ip: Option[IpAddress], port: Option[Port]] =
|
|
||||||
try:
|
|
||||||
# Try IPv4 first
|
|
||||||
let ipv4Result = ma[multiCodec("ip4")]
|
|
||||||
let ip =
|
|
||||||
if ipv4Result.isOk:
|
|
||||||
let ipBytes = ipv4Result.get().protoArgument().expect("Invalid IPv4 format")
|
|
||||||
let ipArray = [ipBytes[0], ipBytes[1], ipBytes[2], ipBytes[3]]
|
|
||||||
some(IpAddress(family: IPv4, address_v4: ipArray))
|
|
||||||
else:
|
|
||||||
# Try IPv6 if IPv4 not found
|
|
||||||
let ipv6Result = ma[multiCodec("ip6")]
|
|
||||||
if ipv6Result.isOk:
|
|
||||||
let ipBytes = ipv6Result.get().protoArgument().expect("Invalid IPv6 format")
|
|
||||||
var ipArray: array[16, byte]
|
|
||||||
for i in 0 .. 15:
|
|
||||||
ipArray[i] = ipBytes[i]
|
|
||||||
some(IpAddress(family: IPv6, address_v6: ipArray))
|
|
||||||
else:
|
|
||||||
none(IpAddress)
|
|
||||||
|
|
||||||
# Get TCP Port
|
|
||||||
let portResult = ma[multiCodec("tcp")]
|
|
||||||
let port =
|
|
||||||
if portResult.isOk:
|
|
||||||
let portBytes = portResult.get().protoArgument().expect("Invalid port format")
|
|
||||||
some(Port(fromBytesBE(uint16, portBytes)))
|
|
||||||
else:
|
|
||||||
none(Port)
|
|
||||||
(ip: ip, port: port)
|
|
||||||
except Exception:
|
|
||||||
(ip: none(IpAddress), port: none(Port))
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{.push raises: [].}
|
{.push raises: [].}
|
||||||
|
|
||||||
import std/[net, tables, hashes, options], pkg/results, chronos, chronicles
|
import std/[net, options], pkg/results, chronos, chronicles
|
||||||
|
|
||||||
import pkg/libp2p
|
import pkg/libp2p
|
||||||
|
|
||||||
@ -9,54 +9,42 @@ type NatStrategy* = enum
|
|||||||
NatUpnp
|
NatUpnp
|
||||||
NatPmp
|
NatPmp
|
||||||
|
|
||||||
func isGlobalUnicast*(address: TransportAddress): bool =
|
proc getRouteIpv4*(): Result[IpAddress, cstring] =
|
||||||
if address.isGlobal() and address.isUnicast(): true else: false
|
let
|
||||||
|
publicAddress = TransportAddress(
|
||||||
|
family: AddressFamily.IPv4, address_v4: [1'u8, 1, 1, 1], port: Port(0)
|
||||||
|
)
|
||||||
|
route = getBestRoute(publicAddress)
|
||||||
|
|
||||||
func isGlobalUnicast*(address: IpAddress): bool =
|
if route.source.isUnspecified():
|
||||||
let a = initTAddress(address, Port(0))
|
err("No best ipv4 route found")
|
||||||
a.isGlobalUnicast()
|
|
||||||
|
|
||||||
proc getRoute(publicAddress: TransportAddress): Result[IpAddress, cstring] =
|
|
||||||
let route = getBestRoute(publicAddress)
|
|
||||||
|
|
||||||
if route.source.family == AddressFamily.None or route.source.isUnspecified():
|
|
||||||
err("No best route found")
|
|
||||||
else:
|
else:
|
||||||
let ip =
|
let ip =
|
||||||
try:
|
try:
|
||||||
route.source.address()
|
route.source.address()
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
# This should not occur really.
|
|
||||||
error "Address conversion error", exception = e.name, msg = e.msg
|
error "Address conversion error", exception = e.name, msg = e.msg
|
||||||
return err("Invalid IP address")
|
return err("Invalid IP address")
|
||||||
ok(ip)
|
ok(ip)
|
||||||
|
|
||||||
proc getRouteIpv4*(): Result[IpAddress, cstring] =
|
|
||||||
# Avoiding Exception with initTAddress and can't make it work with static.
|
|
||||||
# Note: `publicAddress` is only used an "example" IP to find the best route,
|
|
||||||
# no data is send over the network to this IP!
|
|
||||||
let publicAddress = TransportAddress(
|
|
||||||
family: AddressFamily.IPv4, address_v4: [1'u8, 1, 1, 1], port: Port(0)
|
|
||||||
)
|
|
||||||
|
|
||||||
return getRoute(publicAddress)
|
|
||||||
|
|
||||||
proc getRouteIpv6*(): Result[IpAddress, cstring] =
|
proc getRouteIpv6*(): Result[IpAddress, cstring] =
|
||||||
# Note: `googleDnsIpv6` is only used as an "example" IP to find the best route,
|
|
||||||
# no data is sent over the network to this IP!
|
|
||||||
const googleDnsIpv6 = TransportAddress(
|
const googleDnsIpv6 = TransportAddress(
|
||||||
family: AddressFamily.IPv6,
|
family: AddressFamily.IPv6,
|
||||||
# 2001:4860:4860::8888
|
|
||||||
address_v6: [32'u8, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 136],
|
address_v6: [32'u8, 1, 72, 96, 72, 96, 0, 0, 0, 0, 0, 0, 0, 0, 136, 136],
|
||||||
port: Port(0),
|
port: Port(0),
|
||||||
)
|
)
|
||||||
|
let route = getBestRoute(googleDnsIpv6)
|
||||||
|
if route.source.isUnspecified():
|
||||||
|
return err("No best ipv6 route found")
|
||||||
|
try:
|
||||||
|
ok(route.source.address())
|
||||||
|
except ValueError as e:
|
||||||
|
error "Address conversion error", exception = e.name, msg = e.msg
|
||||||
|
err("Invalid IP address")
|
||||||
|
|
||||||
return getRoute(googleDnsIpv6)
|
|
||||||
|
|
||||||
# If bindIp is a anyLocal address (0.0.0.0 or ::),
|
|
||||||
# the function will find the best ip address.
|
|
||||||
# Otherwise, it will just return the ip as it is.
|
|
||||||
proc getBestLocalAddress*(bindIp: IpAddress): Option[IpAddress] =
|
proc getBestLocalAddress*(bindIp: IpAddress): Option[IpAddress] =
|
||||||
|
## If bindIp is anyLocal (0.0.0.0 or ::), finds the best local IP via routing table.
|
||||||
|
## Otherwise returns bindIp as-is.
|
||||||
let bindAddress = initTAddress(bindIp, Port(0))
|
let bindAddress = initTAddress(bindIp, Port(0))
|
||||||
if bindAddress.isAnyLocal():
|
if bindAddress.isAnyLocal():
|
||||||
let ip =
|
let ip =
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import std/json
|
import std/json
|
||||||
import std/options
|
import std/options
|
||||||
import std/sequtils
|
|
||||||
import pkg/chronos
|
import pkg/chronos
|
||||||
import pkg/questionable/results
|
import pkg/questionable/results
|
||||||
|
|
||||||
|
|||||||
@ -321,3 +321,11 @@ proc withNatScheduleInterval*(
|
|||||||
for config in startConfig.configs.mitems:
|
for config in startConfig.configs.mitems:
|
||||||
config.addCliOption("--nat-schedule-interval", $scheduleInterval)
|
config.addCliOption("--nat-schedule-interval", $scheduleInterval)
|
||||||
return startConfig
|
return startConfig
|
||||||
|
|
||||||
|
proc withExtIp*(
|
||||||
|
self: StorageConfigs, ip = "127.0.0.1"
|
||||||
|
): StorageConfigs {.raises: [StorageConfigError].} =
|
||||||
|
var startConfig = self
|
||||||
|
for config in startConfig.configs.mitems:
|
||||||
|
config.addCliOption("--nat", "extip:" & ip)
|
||||||
|
return startConfig
|
||||||
|
|||||||
@ -1,67 +1 @@
|
|||||||
import std/[unittest, net, options]
|
discard
|
||||||
import pkg/chronos
|
|
||||||
import ../../storage/utils/natutils
|
|
||||||
|
|
||||||
suite "isGlobalUnicast":
|
|
||||||
test "localhost IPv4 is not global unicast":
|
|
||||||
check not isGlobalUnicast(parseIpAddress("127.0.0.1"))
|
|
||||||
|
|
||||||
test "unspecified IPv4 is not global unicast":
|
|
||||||
check not isGlobalUnicast(parseIpAddress("0.0.0.0"))
|
|
||||||
|
|
||||||
test "link-local IPv4 is not global unicast":
|
|
||||||
check not isGlobalUnicast(parseIpAddress("169.254.1.1"))
|
|
||||||
|
|
||||||
test "private IPv4 is not global unicast":
|
|
||||||
check not isGlobalUnicast(parseIpAddress("10.0.0.1"))
|
|
||||||
|
|
||||||
test "public IPv4 is global unicast":
|
|
||||||
check isGlobalUnicast(parseIpAddress("8.8.8.8"))
|
|
||||||
|
|
||||||
test "localhost IPv6 is not global unicast":
|
|
||||||
check not isGlobalUnicast(parseIpAddress("::1"))
|
|
||||||
|
|
||||||
test "unspecified IPv6 is not global unicast":
|
|
||||||
check not isGlobalUnicast(parseIpAddress("::"))
|
|
||||||
|
|
||||||
test "link-local IPv6 is not global unicast":
|
|
||||||
check not isGlobalUnicast(parseIpAddress("fe80::1"))
|
|
||||||
|
|
||||||
test "private IPv6 is not global unicast":
|
|
||||||
check not isGlobalUnicast(parseIpAddress("fc00::1"))
|
|
||||||
|
|
||||||
test "public IPv6 is global unicast":
|
|
||||||
check isGlobalUnicast(parseIpAddress("2606:4700::1"))
|
|
||||||
|
|
||||||
suite "getRoute":
|
|
||||||
test "getRouteIpv4 returns a valid IPv4":
|
|
||||||
let res = getRouteIpv4()
|
|
||||||
|
|
||||||
check res.isOk
|
|
||||||
check res.get().family == IpAddressFamily.IPv4
|
|
||||||
|
|
||||||
test "getRouteIpv6 returns a valid IPv6":
|
|
||||||
let res = getRouteIpv6()
|
|
||||||
# If the machine does not have a global route because
|
|
||||||
# it is not configured for IPv6, the test will fail
|
|
||||||
# because it didn't find the best route. In that case,
|
|
||||||
# we can just skip the test, because it is not a problem
|
|
||||||
# with the test itself but the machine configuration.
|
|
||||||
if res.isErr:
|
|
||||||
check res.error == "No best route found"
|
|
||||||
else:
|
|
||||||
check res.get().family == IpAddressFamily.IPv6
|
|
||||||
|
|
||||||
suite "getBestLocalAddress":
|
|
||||||
test "specific IPv4 is returned as it is":
|
|
||||||
let ip = parseIpAddress("192.168.1.1")
|
|
||||||
check getBestLocalAddress(ip) == some(ip)
|
|
||||||
|
|
||||||
test "specific IPv6 is returned as it is":
|
|
||||||
let ip = parseIpAddress("2606:4700::1")
|
|
||||||
check getBestLocalAddress(ip) == some(ip)
|
|
||||||
|
|
||||||
test "0.0.0.0 resolves to a local IPv4":
|
|
||||||
let res = getBestLocalAddress(parseIpAddress("0.0.0.0"))
|
|
||||||
check res.isSome
|
|
||||||
check res.get().family == IpAddressFamily.IPv4
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user