2025-12-18 18:23:09 +01:00
|
|
|
## Logos Storage
|
2022-11-01 18:58:41 -06:00
|
|
|
## Copyright (c) 2022 Status Research & Development GmbH
|
|
|
|
|
## Licensed under either of
|
|
|
|
|
## * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE))
|
|
|
|
|
## * MIT license ([LICENSE-MIT](LICENSE-MIT))
|
|
|
|
|
## at your option.
|
|
|
|
|
## This file may not be copied, modified, or distributed except according to
|
|
|
|
|
## those terms.
|
|
|
|
|
|
2025-12-11 10:03:43 +01:00
|
|
|
{.push raises: [], gcsafe.}
|
2022-11-01 18:58:41 -06:00
|
|
|
|
2025-12-11 22:03:36 +01:00
|
|
|
import std/net
|
2022-11-01 18:58:41 -06:00
|
|
|
import std/strutils
|
|
|
|
|
import std/options
|
|
|
|
|
|
|
|
|
|
import pkg/libp2p
|
2026-06-10 10:54:02 +04:00
|
|
|
import pkg/libp2p/wire
|
2026-06-05 19:49:29 +04:00
|
|
|
import pkg/stew/endians2
|
2022-11-01 18:58:41 -06:00
|
|
|
|
|
|
|
|
func remapAddr*(
|
2023-06-22 08:11:18 -07:00
|
|
|
address: MultiAddress,
|
2025-01-10 15:12:37 +01:00
|
|
|
ip: Option[IpAddress] = IpAddress.none,
|
2023-06-22 08:11:18 -07:00
|
|
|
port: Option[Port] = Port.none,
|
2026-05-05 14:58:26 +04:00
|
|
|
protocol: Option[string] = string.none,
|
2023-06-22 08:11:18 -07:00
|
|
|
): MultiAddress =
|
2026-05-05 14:58:26 +04:00
|
|
|
## Remap addresses to new IP, port, and/or transport protocol (e.g. "tcp" → "udp")
|
2022-11-01 18:58:41 -06:00
|
|
|
##
|
2026-06-05 18:54:06 +04:00
|
|
|
## Assumes a /ip4|ip6/<ip>/tcp|udp/<port> address: anything else crashes (Defect).
|
2022-11-01 18:58:41 -06:00
|
|
|
|
|
|
|
|
var parts = ($address).split("/")
|
|
|
|
|
|
|
|
|
|
parts[2] =
|
|
|
|
|
if ip.isSome:
|
|
|
|
|
$ip.get
|
|
|
|
|
else:
|
|
|
|
|
parts[2]
|
|
|
|
|
|
2026-05-05 14:58:26 +04:00
|
|
|
parts[3] =
|
|
|
|
|
if protocol.isSome:
|
|
|
|
|
protocol.get
|
|
|
|
|
else:
|
|
|
|
|
parts[3]
|
|
|
|
|
|
2022-11-01 18:58:41 -06:00
|
|
|
parts[4] =
|
|
|
|
|
if port.isSome:
|
|
|
|
|
$port.get
|
|
|
|
|
else:
|
|
|
|
|
parts[4]
|
|
|
|
|
|
|
|
|
|
MultiAddress.init(parts.join("/")).expect("Should construct multiaddress")
|
2025-01-09 23:41:22 +05:30
|
|
|
|
2026-06-04 14:37:47 +04:00
|
|
|
func getTcpPort*(ma: MultiAddress): Option[Port] =
|
2026-06-05 19:49:29 +04:00
|
|
|
## Extracts the TCP port from a multiaddress; none when there is no TCP part.
|
|
|
|
|
let tcpPart = ma[multiCodec("tcp")]
|
|
|
|
|
if tcpPart.isErr:
|
|
|
|
|
return Port.none
|
|
|
|
|
let portBytes = tcpPart.get().protoArgument()
|
|
|
|
|
if portBytes.isErr or portBytes.get().len != 2:
|
|
|
|
|
return Port.none
|
|
|
|
|
some(Port(fromBytesBE(uint16, portBytes.get())))
|
2026-06-04 14:37:47 +04:00
|
|
|
|
2026-06-10 10:54:02 +04:00
|
|
|
proc hasPublicRelayTransport*(ma: MultiAddress): bool =
|
|
|
|
|
## True when ``ma`` is a circuit address whose relay is publicly dialable.
|
|
|
|
|
## A circuit address is <relay wire addr>/p2p/<relayId>/p2p-circuit; the part
|
|
|
|
|
## before /p2p/ is the relay's wire address, which isPublicMA can check.
|
|
|
|
|
## Unlike libp2p's publicRoutableAddressPolicy we drop non-public relays: our
|
|
|
|
|
## relay path only runs on a genuine NAT, where the relay is always public.
|
|
|
|
|
let relayWireStr = ($ma).split("/p2p/")[0]
|
|
|
|
|
let relayWireAddr = MultiAddress.init(relayWireStr).valueOr:
|
|
|
|
|
return false
|
|
|
|
|
relayWireAddr.isPublicMA()
|
|
|
|
|
|
|
|
|
|
proc dialableAddressPolicy*(ma: MultiAddress): bool {.gcsafe, raises: [].} =
|
|
|
|
|
# Use with switchBuilder.withAddressPolicy.
|
|
|
|
|
# Filter the peerInfo.addrs updated by libp2p without
|
|
|
|
|
# declaring another address mapper.
|
|
|
|
|
if ma.isCircuitRelayMA():
|
|
|
|
|
ma.hasPublicRelayTransport()
|
|
|
|
|
else:
|
|
|
|
|
ma.isPublicMA()
|
|
|
|
|
|
2026-02-24 21:03:48 +11:00
|
|
|
proc getMultiAddrWithIpAndTcpPort*(ip: IpAddress, port: Port): MultiAddress =
|
|
|
|
|
## Creates a MultiAddress with the specified IP address and TCP port
|
2026-06-10 10:54:02 +04:00
|
|
|
##
|
2026-02-24 21:03:48 +11:00
|
|
|
## Parameters:
|
|
|
|
|
## - ip: A valid IP address (IPv4 or IPv6)
|
|
|
|
|
## - port: The TCP port number
|
|
|
|
|
##
|
|
|
|
|
## Returns:
|
|
|
|
|
## A MultiAddress in the format "/ip4/<address>/tcp/<port>" or "/ip6/<address>/tcp/<port>"
|
|
|
|
|
|
|
|
|
|
let ipFamily = if ip.family == IpAddressFamily.IPv4: "/ip4/" else: "/ip6/"
|
|
|
|
|
return MultiAddress.init(ipFamily & $ip & "/tcp/" & $port).expect(
|
|
|
|
|
"Failed to construct multiaddress with IP and TCP port"
|
|
|
|
|
)
|