2022-11-04 09:52:27 +00:00
|
|
|
when (NimMajor, NimMinor) < (1, 4):
|
|
|
|
{.push raises: [Defect].}
|
|
|
|
else:
|
|
|
|
{.push raises: [].}
|
2021-07-16 15:13:36 +00:00
|
|
|
|
2024-05-16 20:29:11 +00:00
|
|
|
import std/[options, strutils, net]
|
|
|
|
import chronicles, eth/net/nat, stew/results, nativesockets
|
2020-09-01 02:09:54 +00:00
|
|
|
|
2021-07-16 15:13:36 +00:00
|
|
|
logScope:
|
|
|
|
topics = "nat"
|
|
|
|
|
2024-03-15 23:08:47 +00:00
|
|
|
proc setupNat*(
|
|
|
|
natConf, clientId: string, tcpPort, udpPort: Port
|
|
|
|
): Result[
|
|
|
|
tuple[ip: Option[IpAddress], tcpPort: Option[Port], udpPort: Option[Port]], string
|
|
|
|
] {.gcsafe.} =
|
|
|
|
let strategy =
|
|
|
|
case natConf.toLowerAscii()
|
|
|
|
of "any": NatAny
|
|
|
|
of "none": NatNone
|
|
|
|
of "upnp": NatUpnp
|
|
|
|
of "pmp": NatPmp
|
|
|
|
else: NatNone
|
|
|
|
|
|
|
|
var endpoint:
|
|
|
|
tuple[ip: Option[IpAddress], tcpPort: Option[Port], udpPort: Option[Port]]
|
2020-09-01 02:09:54 +00:00
|
|
|
|
2023-05-17 16:32:53 +00:00
|
|
|
if strategy != NatNone:
|
|
|
|
let extIp = getExternalIP(strategy)
|
|
|
|
if extIP.isSome():
|
2023-12-14 06:16:39 +00:00
|
|
|
endpoint.ip = some(extIp.get())
|
2023-05-17 16:32:53 +00:00
|
|
|
# RedirectPorts in considered a gcsafety violation
|
2020-09-01 02:09:54 +00:00
|
|
|
# because it obtains the address of a non-gcsafe proc?
|
2021-07-16 15:13:36 +00:00
|
|
|
var extPorts: Option[(Port, Port)]
|
|
|
|
try:
|
2024-03-15 23:08:47 +00:00
|
|
|
extPorts = (
|
|
|
|
{.gcsafe.}:
|
|
|
|
redirectPorts(tcpPort = tcpPort, udpPort = udpPort, description = clientId)
|
|
|
|
)
|
2023-05-17 16:32:53 +00:00
|
|
|
except CatchableError:
|
|
|
|
# TODO: nat.nim Error: can raise an unlisted exception: Exception. Isolate here for now.
|
2021-07-16 15:13:36 +00:00
|
|
|
error "unable to determine external ports"
|
|
|
|
extPorts = none((Port, Port))
|
|
|
|
|
2023-05-17 16:32:53 +00:00
|
|
|
if extPorts.isSome():
|
2020-09-01 02:09:54 +00:00
|
|
|
let (extTcpPort, extUdpPort) = extPorts.get()
|
2021-07-16 15:13:36 +00:00
|
|
|
endpoint.tcpPort = some(extTcpPort)
|
|
|
|
endpoint.udpPort = some(extUdpPort)
|
2023-05-17 16:32:53 +00:00
|
|
|
else: # NatNone
|
|
|
|
if not natConf.startsWith("extip:"):
|
|
|
|
return err("not a valid NAT mechanism: " & $natConf)
|
|
|
|
|
|
|
|
try:
|
|
|
|
# any required port redirection is assumed to be done by hand
|
2024-03-15 23:08:47 +00:00
|
|
|
endpoint.ip = some(parseIpAddress(natConf[6 ..^ 1]))
|
2023-05-17 16:32:53 +00:00
|
|
|
except ValueError:
|
2024-03-15 23:08:47 +00:00
|
|
|
return err("not a valid IP address: " & $natConf[6 ..^ 1])
|
2023-05-17 16:32:53 +00:00
|
|
|
|
|
|
|
return ok(endpoint)
|