-
Notifications
You must be signed in to change notification settings - Fork 25
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
Retrieve multiple IP addresses when resolving a hostname. #58
Conversation
I also want to point out it doesn't make sense to return |
src/dns.rs
Outdated
fn get_host_by_name( | ||
&mut self, | ||
hostname: &str, | ||
addr_type: AddrType, | ||
) -> nb::Result<IpAddr, Self::Error>; | ||
) -> nb::Result<Self::IpAddrIter, Self::Error>; |
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.
Do you have an implementation where this would make sense? It would be helpful to have an example to demonstrate how this is intended to be used in an embedded context (although I do not know if the DNS traits are widely used yet).
cc @MathiasKoch as I believe he's the only one using the DNS traits so far (although I intend to leverage them in the coming weeks). |
I do use them yeah, but they are in no way optimal or ergonomic to use currently, so i am open to anything that improves the current design flaws. I would like to see some kind of reference implementation as well though? Also, if the case is that nb doesn't make sense, which i tend to agree with, perhaps we should just remove it? |
It seems to be difficult to implement something this trait, because the
I think Some kind of asynchronous API is really important for a network stack though, because operations can take a really long time. |
If we use GATs, we could return an Iterator that borrows self. |
GATs are not stable, so we cannot yet use them. |
That's true. To take a slice, it should really take |
Can you please develop a reference implementation to show how these changes would be used? I do not want to merge changes that we aren't sure will work how we'd like. |
Sure, I'll hook it up to nrfxlib. |
@ryan-summers Here's an example implementation: https://github.com/lachlansneff/nrfxlib/blob/109392c6ad2d6d85ab93330ea399a2df2be69e49/src/tcp.rs#L281-L358 One thing I'm unsure of is the intended implementation target of the trait. Is it intended to be implemented on the same type as TcpStack or UdpStack? |
src/dns.rs
Outdated
&mut self, | ||
hostname: &str, | ||
addr_type: AddrType, | ||
) -> nb::Result<Self::IpAddrIter, Self::Error>; | ||
outputs: &'a mut [MaybeUninit<IpAddr>], | ||
) -> Result<&'a [IpAddr], Self::Error>; |
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 think we can just tie the lifetime of 'a
to that of self
. That way, any struct that impl Dns
can just borrow out internal storage. E.g.
struct MyDns {
storage: [IpAddr; 5],
}
impl Dns for MyDns {
fn get_hosts_by_name<'s>(&'s mut self, hostname: &str, addr_type: AddrType) -> Results<&'s [IpAddr], Self::Error> {
&self.storage[..]
}
}
Or something similar? I don't think the user should need to pass in a storage buffer - that's a very c-like paradigm that I don't think is required with the ownership semantics Rust provides
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 really sure about that. It seems like it would restrict implementations to do this one thing. And it would mean that the implementer of the network stack decides how many items a DNS lookup can have.
Returning an iterator would, by far, be the most flexible but as you said, it would require nightly because of GATs.
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.
Can we add a const-generic to this function argument to allow a list of addresses to be returned?
fn get_hosts_by_name<const T: usize>(&mut self, hostname: &str, addr_type: AddrType) -> Result<heapless::Vec<IpAddr, T>, Self::Error>;
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, that'd be fine. I think that'd optimize to pretty much the same thing as passing in a slice.
Generally speaking, yes. There's a single "Network stack" that provides a socket-like API to the application (e.g. |
I came up with an example implementation that returns an iterator that can borrow self without GATs. https://github.com/lachlansneff/nrfxlib/blob/9c814bb69f2cd7cc77ca58dbe095cb6c43b688cc/src/tcp.rs#L267-L379 Apologies for the weird indentation. |
Another option is to call a callback for each IP address returned. |
I also want to point out that because the dns methods take |
I'm going to close this PR and open an issue about changing the embedded-nal API to more closely resemble std::net. |
This only works, because the API you are using internally calls |
This PR changes the
Dns::get_host_by_name
function toDns::get_hosts_by_name
and makes it return an iterator.