2021-04-28 14:20:05 +00:00
|
|
|
# nim-eth
|
2024-01-24 08:09:11 +00:00
|
|
|
# Copyright (c) 2020-2024 Status Research & Development GmbH
|
2021-04-28 14:20:05 +00:00
|
|
|
# Licensed and distributed under either of
|
|
|
|
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
|
|
|
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
|
|
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
|
|
|
2023-05-10 13:50:04 +00:00
|
|
|
{.push raises: [].}
|
2021-04-28 14:20:05 +00:00
|
|
|
|
2020-11-26 17:20:15 +00:00
|
|
|
import
|
2024-01-24 08:09:11 +00:00
|
|
|
std/[tables, hashes, net],
|
|
|
|
stew/results, chronos, chronicles
|
|
|
|
|
|
|
|
export net.IpAddress
|
2020-11-26 17:20:15 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
IpLimits* = object
|
|
|
|
limit*: uint
|
2023-11-10 06:28:21 +00:00
|
|
|
ips: Table[IpAddress, uint]
|
2020-11-26 17:20:15 +00:00
|
|
|
|
2024-01-19 10:15:57 +00:00
|
|
|
func hash*(ip: IpAddress): Hash =
|
2021-11-29 19:58:45 +00:00
|
|
|
case ip.family
|
|
|
|
of IpAddressFamily.IPv6: hash(ip.address_v6)
|
|
|
|
of IpAddressFamily.IPv4: hash(ip.address_v4)
|
2020-11-26 17:20:15 +00:00
|
|
|
|
2023-11-10 06:28:21 +00:00
|
|
|
func inc*(ipLimits: var IpLimits, ip: IpAddress): bool =
|
2020-11-26 17:20:15 +00:00
|
|
|
let val = ipLimits.ips.getOrDefault(ip, 0)
|
|
|
|
if val < ipLimits.limit:
|
|
|
|
ipLimits.ips[ip] = val + 1
|
|
|
|
true
|
|
|
|
else:
|
|
|
|
false
|
|
|
|
|
2023-11-10 06:28:21 +00:00
|
|
|
func dec*(ipLimits: var IpLimits, ip: IpAddress) =
|
2020-11-26 17:20:15 +00:00
|
|
|
let val = ipLimits.ips.getOrDefault(ip, 0)
|
|
|
|
if val == 1:
|
|
|
|
ipLimits.ips.del(ip)
|
|
|
|
elif val > 1:
|
|
|
|
ipLimits.ips[ip] = val - 1
|
2021-03-02 16:13:29 +00:00
|
|
|
|
2023-02-21 08:34:26 +00:00
|
|
|
func isGlobalUnicast*(address: TransportAddress): bool =
|
|
|
|
if address.isGlobal() and address.isUnicast():
|
2021-03-02 16:13:29 +00:00
|
|
|
true
|
2023-02-21 08:34:26 +00:00
|
|
|
else:
|
|
|
|
false
|
2021-03-02 16:13:29 +00:00
|
|
|
|
2023-02-21 08:34:26 +00:00
|
|
|
func isGlobalUnicast*(address: IpAddress): bool =
|
2021-03-02 16:13:29 +00:00
|
|
|
let a = initTAddress(address, Port(0))
|
2023-02-21 08:34:26 +00:00
|
|
|
a.isGlobalUnicast()
|
2021-03-05 20:23:54 +00:00
|
|
|
|
2023-11-10 06:28:21 +00:00
|
|
|
proc getRouteIpv4*(): Result[IpAddress, cstring] =
|
2021-03-05 20:23:54 +00:00
|
|
|
# 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))
|
|
|
|
route = getBestRoute(publicAddress)
|
|
|
|
|
|
|
|
if route.source.isUnspecified():
|
|
|
|
err("No best ipv4 route found")
|
|
|
|
else:
|
|
|
|
let ip = try: route.source.address()
|
|
|
|
except ValueError as e:
|
|
|
|
# This should not occur really.
|
2022-11-16 16:44:00 +00:00
|
|
|
error "Address conversion error", exception = e.name, msg = e.msg
|
2021-03-05 20:23:54 +00:00
|
|
|
return err("Invalid IP address")
|
2023-11-10 06:28:21 +00:00
|
|
|
ok(ip)
|
2024-01-24 08:09:11 +00:00
|
|
|
|
|
|
|
func ipv4*(address: array[4, byte]): IpAddress =
|
|
|
|
IpAddress(family: IPv4, address_v4: address)
|
|
|
|
|
|
|
|
func ipv6*(address: array[16, byte]): IpAddress =
|
|
|
|
IpAddress(family: IPv6, address_v6: address)
|