mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-05-12 22:39:26 +00:00
160 lines
4.9 KiB
Nim
160 lines
4.9 KiB
Nim
import std/[net, importutils, envvars]
|
|
import pkg/chronos
|
|
import ../../storage/utils/natutils
|
|
import pkg/libp2p/[multiaddress, multihash, multicodec]
|
|
import pkg/libp2p/protocols/connectivity/autonat/types
|
|
import pkg/libp2p/protocols/connectivity/relay/client as relayClientModule
|
|
import pkg/libp2p/services/autorelayservice except setup
|
|
|
|
import pkg/results
|
|
|
|
import ./helpers
|
|
import ../asynctest
|
|
import ../../storage/nat
|
|
import ../../storage/discovery
|
|
import ../../storage/rng
|
|
import ../../storage/utils
|
|
|
|
privateAccess(NatMapper)
|
|
|
|
type MockUpnpDevice = ref object of UpnpDevice
|
|
deletedPorts: seq[(Port, NatIpProtocol)]
|
|
|
|
method discover*(d: MockUpnpDevice): Result[int, cstring] {.gcsafe.} =
|
|
ok(1)
|
|
|
|
method selectIGD*(d: MockUpnpDevice): SelectIGDResult {.gcsafe.} =
|
|
IGDFound
|
|
|
|
method deletePortMapping*(
|
|
d: MockUpnpDevice, port: Port, proto: NatIpProtocol
|
|
): Result[void, string] {.gcsafe.} =
|
|
d.deletedPorts.add((port, proto))
|
|
ok()
|
|
|
|
type MockNatMapper = ref object of NatMapper
|
|
mappedPorts: Option[(Port, Port)]
|
|
|
|
method mapNatPorts*(
|
|
m: MockNatMapper
|
|
): Future[Option[(Port, Port)]] {.async: (raises: [CancelledError]), gcsafe.} =
|
|
m.mappedPorts
|
|
|
|
suite "NAT - NatMapper.close":
|
|
test "does nothing when no upnp mapping":
|
|
let mapper = MockNatMapper(
|
|
natConfig: NatConfig(hasExtIp: false, nat: NatAuto),
|
|
tcpPort: Port(8080),
|
|
discoveryPort: Port(8090),
|
|
)
|
|
let device = MockUpnpDevice()
|
|
mapper.close(device)
|
|
check device.deletedPorts.len == 0
|
|
|
|
test "deletes tcp and udp ports when upnp mapping exists":
|
|
let mapper = MockNatMapper(
|
|
natConfig: NatConfig(hasExtIp: false, nat: NatAuto),
|
|
tcpPort: Port(8080),
|
|
discoveryPort: Port(8090),
|
|
)
|
|
mapper.hasUpnpMapping = true
|
|
let device = MockUpnpDevice()
|
|
mapper.close(device)
|
|
check device.deletedPorts ==
|
|
@[(Port(8080), NatIpProtocol.Tcp), (Port(8090), NatIpProtocol.Udp)]
|
|
|
|
asyncchecksuite "NAT - handleNatStatus":
|
|
var sw: Switch
|
|
var key: PrivateKey
|
|
var disc: Discovery
|
|
var autoRelay: AutoRelayService
|
|
|
|
setup:
|
|
autoRelay =
|
|
AutoRelayService.new(1, relayClientModule.RelayClient.new(), nil, Rng.instance())
|
|
key = PrivateKey.random(Rng.instance[]).get()
|
|
disc = Discovery.new(key, announceAddrs = @[])
|
|
sw = newStandardSwitch()
|
|
await sw.start()
|
|
|
|
teardown:
|
|
await sw.stop()
|
|
|
|
if autoRelay.isRunning:
|
|
discard await autoRelay.stop(sw)
|
|
|
|
let discoveryPort = Port(8090)
|
|
|
|
test "handleNatStatus announces mapped address when NotReachable and UPnP succeeds":
|
|
let dialBack = MultiAddress.init("/ip4/1.2.3.4/tcp/8080").expect("valid")
|
|
let mapper = MockNatMapper(mappedPorts: some((Port(9000), Port(9001))))
|
|
|
|
await mapper.handleNatStatus(
|
|
NotReachable, Opt.some(dialBack), discoveryPort, disc, sw, autoRelay
|
|
)
|
|
|
|
check disc.announceAddrs ==
|
|
@[MultiAddress.init("/ip4/1.2.3.4/tcp/9000").expect("valid")]
|
|
check not autoRelay.isRunning
|
|
|
|
test "handleNatStatus starts autoRelay when NotReachable and UPnP failed":
|
|
let mapper = MockNatMapper(mappedPorts: none((Port, Port)))
|
|
|
|
await mapper.handleNatStatus(
|
|
NotReachable, Opt.none(MultiAddress), discoveryPort, disc, sw, autoRelay
|
|
)
|
|
|
|
check autoRelay.isRunning
|
|
|
|
test "handleNatStatus starts autoRelay when NotReachable and mapping fails":
|
|
let dialBack = MultiAddress.init("/ip4/1.2.3.4/tcp/8080").expect("valid")
|
|
let mapper = MockNatMapper(mappedPorts: none((Port, Port)))
|
|
|
|
await mapper.handleNatStatus(
|
|
NotReachable, Opt.some(dialBack), discoveryPort, disc, sw, autoRelay
|
|
)
|
|
|
|
check autoRelay.isRunning
|
|
check disc.announceAddrs == newSeq[MultiAddress]()
|
|
|
|
test "handleNatStatus does not announce address when Reachable and no dialBackAddr":
|
|
let mapper = MockNatMapper(mappedPorts: none((Port, Port)))
|
|
|
|
await mapper.handleNatStatus(
|
|
Reachable, Opt.none(MultiAddress), discoveryPort, disc, sw, autoRelay
|
|
)
|
|
|
|
check disc.announceAddrs == newSeq[MultiAddress]()
|
|
check not autoRelay.isRunning
|
|
|
|
test "handleNatStatus stops relay and announces dialBackAddr when Reachable":
|
|
let dialBack = MultiAddress.init("/ip4/1.2.3.4/tcp/8080").expect("valid")
|
|
let mapper = MockNatMapper(mappedPorts: none((Port, Port)))
|
|
|
|
discard await autorelayservice.setup(autoRelay, sw)
|
|
await mapper.handleNatStatus(
|
|
Reachable, Opt.some(dialBack), discoveryPort, disc, sw, autoRelay
|
|
)
|
|
|
|
check not autoRelay.isRunning
|
|
check disc.announceAddrs == @[dialBack]
|
|
|
|
suite "NAT - UPnP port mapping (requires NAT_TEST_UPNP=1)":
|
|
test "mapPorts and cleanup":
|
|
if getEnv("NAT_TEST_UPNP") != "1":
|
|
skip()
|
|
|
|
let res = UpnpDevice.init()
|
|
check res.isOk
|
|
|
|
let device = res.value
|
|
let ports = device.mapPorts(Port(8101), Port(8090))
|
|
check ports.isSome
|
|
|
|
let (tcp, udp) = ports.get()
|
|
check tcp == Port(8101)
|
|
check udp == Port(8090)
|
|
|
|
check device.deletePortMapping(Port(8101), NatIpProtocol.Tcp).isOk
|
|
check device.deletePortMapping(Port(8090), NatIpProtocol.Udp).isOk
|