-
Notifications
You must be signed in to change notification settings - Fork 52
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(service): add wildcard address resolver #1099
Merged
Merged
Changes from 25 commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
9914618
add wildcard addr resolver
diegomrsantos 7990325
add test
diegomrsantos 04f8b83
add withvalue for result
diegomrsantos d04d3a0
add doc comments
diegomrsantos 368ab10
add doc comments
diegomrsantos d2a4e84
removes scheduler and some cleanup
diegomrsantos 399041a
move peer id concatenation to switch
diegomrsantos 90b9734
remove unnecessary check
diegomrsantos 36ae955
remove peer id concat
diegomrsantos 19b8273
remove redundant test
diegomrsantos 0a2df2b
add docs
diegomrsantos 4196b4a
make addr provider a proc
diegomrsantos 51339c2
formatting
diegomrsantos 99dbeaf
remove toOpt
diegomrsantos d834b3e
remove echo
diegomrsantos 2216dac
Update libp2p/services/wildcardresolverservice.nim
diegomrsantos c9e877e
fix test
diegomrsantos 0e472ef
fix test
diegomrsantos 5719454
Revert "fix test"
diegomrsantos 7bbc071
Revert "fix test"
diegomrsantos 0b78975
Revert "enable resolver by default"
diegomrsantos c11586c
enable service by default in builder
diegomrsantos edf91dd
remove stale field
diegomrsantos 54dbf1f
fix test
diegomrsantos 8c19cac
fix autonatservice test
diegomrsantos 1bb1c1a
removing code that end up here by accident during reverts and cherry-…
diegomrsantos e0a380e
uncomment line
diegomrsantos 2a1e1f0
fix hpservice test and remove proc
diegomrsantos 7b803ad
fix identify test
diegomrsantos 385a595
improve test
diegomrsantos 433a2ba
Merge branch 'master' into anyaddr-resolver
diegomrsantos 65c3e88
unnecessary
diegomrsantos 2235b4b
Merge branch 'master' into anyaddr-resolver
diegomrsantos ea34224
fix doc
diegomrsantos c4bcd53
add comment
diegomrsantos 90bc65f
show addrs in "Dialing peer" log
diegomrsantos File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
# Nim-LibP2P | ||
# Copyright (c) 2024 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. | ||
|
||
{.push raises: [].} | ||
|
||
import std/sequtils | ||
import stew/[byteutils, results, endians2] | ||
import chronos, chronos/transports/[osnet, ipnet], chronicles | ||
import ../[multiaddress, multicodec] | ||
import ../switch | ||
|
||
logScope: | ||
topics = "libp2p wildcardresolverservice" | ||
|
||
type | ||
WildcardAddressResolverService* = ref object of Service | ||
## Service used to resolve wildcard addresses of the type "0.0.0.0" for IPv4 or "::" for IPv6. | ||
## When used with a `Switch`, this service will be automatically set up and stopped | ||
## when the switch starts and stops. This is facilitated by adding the service to the switch's | ||
## list of services using the `.withServices(@[svc])` method in the `SwitchBuilder`. | ||
networkInterfaceProvider: NetworkInterfaceProvider | ||
## Provides a list of network addresses. | ||
addressMapper: AddressMapper | ||
## An implementation of an address mapper that takes a list of listen addresses and expands each wildcard address | ||
## to the respective list of interface addresses. As an example, if the listen address is 0.0.0.0:4001 | ||
## and the machine has 2 interfaces with IPs 172.217.11.174 and 64.233.177.113, the address mapper will | ||
## expand the wildcard address to 172.217.11.174:4001 and 64.233.177.113:4001. | ||
|
||
NetworkInterfaceProvider* = | ||
proc(addrFamily: AddressFamily): seq[InterfaceAddress] {.gcsafe, raises: [].} | ||
|
||
proc isLoopbackOrUp(networkInterface: NetworkInterface): bool = | ||
if (networkInterface.ifType == IfSoftwareLoopback) or | ||
(networkInterface.state == StatusUp): true else: false | ||
|
||
proc getAddresses(addrFamily: AddressFamily): seq[InterfaceAddress] = | ||
## This method retrieves the addresses of network interfaces based on the specified address family. | ||
lchenut marked this conversation as resolved.
Show resolved
Hide resolved
|
||
## | ||
## The `getAddresses` method filters the available network interfaces to include only | ||
## those that are either loopback or up. It then collects all the addresses from these | ||
## interfaces and filters them to match the provided address family. | ||
## | ||
## Parameters: | ||
## - `addrFamily`: The address family to filter the network addresses (e.g., `AddressFamily.IPv4` or `AddressFamily.IPv6`). | ||
## | ||
## Returns: | ||
## - A sequence of `InterfaceAddress` objects that match the specified address family. | ||
let | ||
interfaces = getInterfaces().filterIt(it.isLoopbackOrUp()) | ||
flatInterfaceAddresses = concat(interfaces.mapIt(it.addresses)) | ||
filteredInterfaceAddresses = | ||
flatInterfaceAddresses.filterIt(it.host.family == addrFamily) | ||
return filteredInterfaceAddresses | ||
|
||
proc new*( | ||
T: typedesc[WildcardAddressResolverService], | ||
networkInterfaceProvider: NetworkInterfaceProvider = getAddresses, | ||
): T = | ||
## This procedure initializes a new `WildcardAddressResolverService` with the provided network interface provider. | ||
## | ||
## Parameters: | ||
## - `T`: The type descriptor for `WildcardAddressResolverService`. | ||
## - `networkInterfaceProvider`: A provider that offers access to network interfaces. Defaults to a new instance of `NetworkInterfaceProvider`. | ||
## | ||
## Returns: | ||
## - A new instance of `WildcardAddressResolverService`. | ||
return T(networkInterfaceProvider: networkInterfaceProvider) | ||
|
||
proc getProtocolArgument*(ma: MultiAddress, codec: MultiCodec): MaResult[seq[byte]] = | ||
var buffer: seq[byte] | ||
for item in ma: | ||
let | ||
ritem = ?item | ||
code = ?ritem.protoCode() | ||
if code == codec: | ||
let arg = ?ritem.protoAddress() | ||
return ok(arg) | ||
|
||
err("Multiaddress codec has not been found") | ||
|
||
proc getWildcardMultiAddresses( | ||
interfaceAddresses: seq[InterfaceAddress], protocol: Protocol, port: Port | ||
): seq[MultiAddress] = | ||
var addresses: seq[MultiAddress] | ||
for ifaddr in interfaceAddresses: | ||
var address = ifaddr.host | ||
address.port = port | ||
MultiAddress.init(address, protocol).withValue(maddress): | ||
addresses.add(maddress) | ||
addresses | ||
|
||
proc getWildcardAddress( | ||
maddress: MultiAddress, | ||
multiCodec: MultiCodec, | ||
anyAddr: openArray[uint8], | ||
addrFamily: AddressFamily, | ||
port: Port, | ||
networkInterfaceProvider: NetworkInterfaceProvider, | ||
): seq[MultiAddress] = | ||
var addresses: seq[MultiAddress] | ||
maddress.getProtocolArgument(multiCodec).withValue(address): | ||
if address == anyAddr: | ||
let filteredInterfaceAddresses = networkInterfaceProvider(addrFamily) | ||
addresses.add( | ||
getWildcardMultiAddresses(filteredInterfaceAddresses, IPPROTO_TCP, port) | ||
) | ||
else: | ||
addresses.add(maddress) | ||
return addresses | ||
|
||
proc expandWildcardAddresses( | ||
networkInterfaceProvider: NetworkInterfaceProvider, listenAddrs: seq[MultiAddress] | ||
): seq[MultiAddress] = | ||
var addresses: seq[MultiAddress] | ||
# In this loop we expand bound addresses like `0.0.0.0` and `::` to list of interface addresses. | ||
for listenAddr in listenAddrs: | ||
if TCP_IP.matchPartial(listenAddr): | ||
listenAddr.getProtocolArgument(multiCodec("tcp")).withValue(portArg): | ||
let port = Port(uint16.fromBytesBE(portArg)) | ||
if IP4.matchPartial(listenAddr): | ||
let wildcardAddresses = getWildcardAddress( | ||
listenAddr, | ||
multiCodec("ip4"), | ||
AnyAddress.address_v4, | ||
AddressFamily.IPv4, | ||
port, | ||
networkInterfaceProvider, | ||
) | ||
addresses.add(wildcardAddresses) | ||
elif IP6.matchPartial(listenAddr): | ||
let wildcardAddresses = getWildcardAddress( | ||
listenAddr, | ||
multiCodec("ip6"), | ||
AnyAddress6.address_v6, | ||
AddressFamily.IPv6, | ||
port, | ||
networkInterfaceProvider, | ||
) | ||
addresses.add(wildcardAddresses) | ||
else: | ||
addresses.add(listenAddr) | ||
else: | ||
addresses.add(listenAddr) | ||
addresses | ||
|
||
method setup*( | ||
self: WildcardAddressResolverService, switch: Switch | ||
): Future[bool] {.async.} = | ||
## Sets up the `WildcardAddressResolverService`. | ||
## | ||
## This method adds the address mapper to the peer's list of address mappers. | ||
## | ||
## Parameters: | ||
## - `self`: The instance of `WildcardAddressResolverService` being set up. | ||
## - `switch`: The switch context in which the service operates. | ||
## | ||
## Returns: | ||
## - A `Future[bool]` that resolves to `true` if the setup was successful, otherwise `false`. | ||
self.addressMapper = proc( | ||
listenAddrs: seq[MultiAddress] | ||
): Future[seq[MultiAddress]] {.async.} = | ||
return expandWildcardAddresses(self.networkInterfaceProvider, listenAddrs) | ||
|
||
debug "Setting up WildcardAddressResolverService" | ||
let hasBeenSetup = await procCall Service(self).setup(switch) | ||
if hasBeenSetup: | ||
switch.peerInfo.addressMappers.add(self.addressMapper) | ||
return hasBeenSetup | ||
|
||
method run*(self: WildcardAddressResolverService, switch: Switch) {.async, public.} = | ||
## Runs the WildcardAddressResolverService for a given switch. | ||
## | ||
## It updates the peer information for the provided switch by running the registered address mapper. Any other | ||
## address mappers that are registered with the switch will also be run. | ||
## | ||
trace "Running WildcardAddressResolverService" | ||
await switch.peerInfo.update() | ||
|
||
method stop*( | ||
self: WildcardAddressResolverService, switch: Switch | ||
): Future[bool] {.async, public.} = | ||
## Stops the WildcardAddressResolverService. | ||
## | ||
## Handles the shutdown process of the WildcardAddressResolverService for a given switch. | ||
## It removes the address mapper from the switch's list of address mappers. | ||
## It then updates the peer information for the provided switch. Any wildcard address wont be resolved anymore. | ||
## | ||
## Parameters: | ||
## - `self`: The instance of the WildcardAddressResolverService. | ||
## - `switch`: The Switch object associated with the service. | ||
## | ||
## Returns: | ||
## - A future that resolves to `true` if the service was successfully stopped, otherwise `false`. | ||
debug "Stopping WildcardAddressResolverService" | ||
let hasBeenStopped = await procCall Service(self).stop(switch) | ||
if hasBeenStopped: | ||
switch.peerInfo.addressMappers.keepItIf(it != self.addressMapper) | ||
await switch.peerInfo.update() | ||
return hasBeenStopped |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI: We should change this to IFT. I'll sync with legal and come back.
We can change this in a follow up PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we change all nim-libp2p files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ill get back once legal gets back to me.
I asked that question :).
In any case, we can do that in a follow up PR.