Open chrysn opened 7 months ago
tl;dr: Does https://github.com/smoltcp-rs/smoltcp/pull/904 fix this for you?
To start this off with some background on where this is coming from: Both QUIC and CoAP, when run as servers, need to know where the incoming packet was sent to, and reply from that very address. It is a frequent source of CoAP interoperability troubles if servers just send from any address (worst because it works most of the time, but when the device gets an extra IP address, suddenly it stops working). Also, this is highly important for distinguishing unicast from multicast messages. This doesn't really come from BSD sockets -- on the contrary, it is hard to do on BSD sockets because they need to go through recvmsg, set the PKTINFO socket option and hope to get the platform specific format of the ancillary data item right when using IP versions smaller than 6. In contrast, the embedded-nal sockets are more oriented toward basic BSD sockets (without recvmsg), and thus are missing crucial functionality for implementing UDP based protocols that are more complex than an Echo server.
On the long run, I think that the sync NAL should migrate to the async NAL's concepts, especially if and when we've ironed out any warts such as this (which I hope is resolved with the PR) or #103.
On the smoltcp side, there is a PR that just fixes this: https://github.com/smoltcp-rs/smoltcp/pull/904. Could you have a look at it to see whether it resolves the problem? An example of how it is used (to implement the bind_multiple_server, even, although through embassy-nal) is available at https://github.com/embassy-rs/embassy/pull/2519
tl;dr: Does smoltcp-rs/smoltcp#904 fix this for you?
Yep, seems to address precisely the issue at hand. Sorry for not looking into what is open w.r.t. PRs in smoltcp
. :)
Also, this is highly important for distinguishing unicast from multicast messages.
Interesting that you mentioned multicast. Did you really mean multicast or broadcast? Because while I can imagine that (a) having access to the 'local' (= destination) IP address in UnconnectedUdp::receive_into
would allow the app code to figure out whether this is a broadcast or a multicast message (the former being important in the context of - say - DHCP servers), lack of full broadcast/multicast support is another feature I'm missing:
std-embedded-nal-async
can't really receive broadcast messages, as it is missing a set_broadcast(true)
callsmoltcp
where the latter in the meantime does support ipv4 and ipv6 multicast as well.This doesn't really come from BSD sockets -- on the contrary, it is hard to do on BSD sockets because they need to go through recvmsg, set the PKTINFO socket option and hope to get the platform specific format of the ancillary data item right when using IP versions smaller than 6. In contrast, the embedded-nal sockets are more oriented toward basic BSD sockets (without recvmsg), and thus are missing crucial functionality for implementing UDP based protocols that are more complex than an Echo server.
On the long run, I think that the sync NAL should migrate to the async NAL's concepts, especially if and when we've ironed out any warts such as this (which I hope is resolved with the PR) or #103.
Agreed.
On the smoltcp side, there is a PR that just fixes this: smoltcp-rs/smoltcp#904. Could you have a look at it to see whether it resolves the problem? An example of how it is used (to implement the bind_multiple_server, even, although through embassy-nal) is available at embassy-rs/embassy#2519
Let me look into this deeper, but as per above - seems to be spot on.
I am talking of multicast -- broadcast only really exists on IPv4 and I barely touch that any more. IPv4 is hard there, because the application needs extra information (from the network stack) to determine whether an address is a broadcast address or not. With IPv6, cases are clear.
Setting up the multicast groups is out of scope for embedded-nal, at least with the current interfaces, but a library could be documented as
To start a CoAP server, run
CoAPServer::new(sock)
for a socket that has been bound to the addresses you want the server to run on (the default port is 5683). If you want it to process multicast requests, join the ff0x::fd group, and any other groups you want to participate in.
I'm curious about the traits you are proposing; they are a welcome addition as they allow the application to do things more automatically, but they are not essential. (Also they seem like the right pool into which I should merge my embedded-nal-tcpextensions :-) ).
I am talking of multicast -- broadcast only really exists on IPv4 and I barely touch that any more. IPv4 is hard there, because the application needs extra information (from the network stack) to determine whether an address is a broadcast address or not. With IPv6, cases are clear.
Setting up the multicast groups is out of scope for embedded-nal, at least with the current interfaces, but a library could be documented as
To start a CoAP server, run
CoAPServer::new(sock)
for a socket that has been bound to the addresses you want the server to run on (the default port is 5683). If you want it to process multicast requests, join the ff0x::fd group, and any other groups you want to participate in.I'm curious about the traits you are proposing; they are a welcome addition as they allow the application to do things more automatically, but they are not essential. (Also they seem like the right pool into which I should merge my embedded-nal-tcpextensions :-) ).
Perhaps I can agree for Multicast
. It would be difficult for me to however swallow that we cannot have
If - you know - our answer for these use cases is - "you need to do it outside the embedded-nal-async
traits", we should probably retire UdpStack
and TcpConnect
in the first place. But if we do this, I would question the value of what's left in embedded-nal-async
as well. I mean, it is really Read
+ Write
for TCP sockets and connected UDP - and these are not even part of embedded-nal-async
but live in embedded-io-async
. So what's left for embedded-nal-async
is some sort of simplistic ReadAndReturnSockAddrs
+ WriteWithSockAddrs
pair of traits that cover the "unconnected" UDP case...
I guess what I'm saying is that - at least for me - the perceived value of embedded-nal-async
was always as much as - or if not more - in the socket factories' traits, as it is in the actual socket traits. :)
I've split this out of #103 as reported by @ivmarkov to keep threads disentangled: