-
Notifications
You must be signed in to change notification settings - Fork 334
feat(iroh)!: allow multiple IP transports, including filtering by interface #3692
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
base: main
Are you sure you want to change the base?
Conversation
|
Documentation for this PR has been generated and is available at: https://n0-computer.github.io/iroh/pr/3692/docs/iroh/ Last updated: 2025-12-19T10:41:21Z |
6726f3c to
479652f
Compare
479652f to
232524f
Compare
|
We could remove the |
well currently they are treated differently internally as an explicit fallback, thats why the difference in configuration exists |
| if sender.is_valid_send_addr(addr) { | ||
| Addr::Ip(addr) => match addr { | ||
| SocketAddr::V4(_) => { | ||
| for sender in self.ip.v4_iter_mut().filter(|s| s.is_valid_send_addr(addr)) { |
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.
It probably makes sense to pass in src: Option<IpAddr> now that we populate that value.
After all, is the value that should first and foremost tell you which interface to use.
matheus23
left a comment
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.
I'm not super convinced this is the right API 🤔
Looking at your example:
let endpoint = Endpoint::builder()
.bind_addr_v4_default("127.0.0.1", 1234)
.bind_addr_v4("192.168.1.2/24".parse()?, 1234) // bind to prefix_len of 24
.bind()
.await?It looks like the configuration for an endpoint that will only send traffic in the local network and localhost.
So let's say quinn produces a datagram that's meant to be sent to 192.168.1.101:1234.
Iroh will then first check this against your 192.168.1.2/24 and find a match. However, it turns out that interface is actually busy, so it continues.
Then it'll see the "default" 127.0.0.1 interface and try to send on that. But obviously it can't send outside localhost, so ideally that should just fail sending, but I think it won't? I'm not actually sure what will happen.
Also another thing about the default socket: What if someone wants to bind a dual-stack socket with [::]? I think that should match against an IPv4 address, but IIUC currently it doesn't?
Minor note: I'm not sure what should happen if you bind multiple sockets to the same port, but different IP addrs. What happens in these cases? I'm not sure.
| /// Does this configuration match to send to the given `dst` address. | ||
| pub(crate) fn is_valid_send_addr(&self, dst: SocketAddr) -> bool { | ||
| match self { | ||
| Self::V4Default { .. } => matches!(dst, SocketAddr::V4(_)), | ||
| Self::V6Default { .. } => matches!(dst, SocketAddr::V6(_)), | ||
| Self::V4 { ip_addr, .. } => match dst { | ||
| SocketAddr::V4(dst_v4) => ip_addr.contains(dst_v4.ip()), | ||
| SocketAddr::V6(_) => false, | ||
| }, | ||
| Self::V6 { | ||
| ip_addr, scope_id, .. | ||
| } => match dst { | ||
| SocketAddr::V6(dst_v6) => { | ||
| if ip_addr.contains(dst_v6.ip()) { | ||
| return true; | ||
| } | ||
| if dst_v6.ip().is_unicast_link_local() { | ||
| // If we have a link local interface, use the scope id | ||
| if *scope_id == dst_v6.scope_id() { | ||
| return true; | ||
| } | ||
| } | ||
| false | ||
| } | ||
| SocketAddr::V4(_) => false, | ||
| }, | ||
| } | ||
| } | ||
| } |
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.
Yeah I agree with Frando here I think: I'm not sure if it's that useful to have the default cases here.
What's the use case for having these be a special case? Make sure they're tried last?
Description
This allows for multiple interfaces to be bound, and be actually used.
You can now use this by passing
The selection of the interface is done internally by first looking at all specific bindings, and then fallbing back to the
defaultversion for this family.Breaking Changes
irohEndpoint::bind_addr_v4toEndpoint::bind_addr_v4_defaultEndpoint::bind_addr_v6toEndpoint::bind_addr_v6_defaultEndpoint::bind_addr_v4Endpoint::bind_addr_v6endpoint::Ipv4Netendpoint::Ipv6Net