pub trait UdpBind {
type Socket: UdpDatagrams;
// Required method
fn bind(&self, local: SocketAddr) -> Result<Self::Socket>;
}Expand description
Bind a UDP socket.
§Why bind is sync where TcpConnect::connect is async
Not for symmetry’s sake in either direction. Binding performs no network
round trip on any runtime this workspace targets — std::net::UdpSocket:: bind is a syscall, tokio::net::UdpSocket::from_std and
async_io::Async::new are registrations, and embassy_net::udp:: UdpSocket::bind returns immediately. connect, by contrast, is a real
handshake and has to be async.
There is also a consumer-side reason, and it is the decisive one: a QUIC
stack asks its runtime to wrap a socket from a synchronous call
(quinn::Runtime::wrap_udp_socket, quinn-0.11.11/src/runtime.rs:24).
An async bind could not serve it, and inventing a second synchronous
method beside an async one would be two ways to say the same thing.
Required Associated Types§
Sourcetype Socket: UdpDatagrams
type Socket: UdpDatagrams
No Send, Sync, 'static or Debug bound here, deliberately.
A QUIC stack needs all four (quinn::AsyncUdpSocket: Send + Sync + Debug + 'static), and the research this crate is built on proposed
putting them on this associated type. They are not here, because a
bound in the trait is paid by every implementer for the benefit of
one consumer, and this seam has an implementer — an embassy-net
backend — for which Send is not free. The bounds live in
hclient_h3::H3’s where clause instead, so the compile error lands
on whoever asked for QUIC rather than on whoever implemented UDP.
TcpConnect::Stream keeps the same property and pays nothing for
it: hclient-native’s FakeStream holds an Rc<()> precisely to
prove that no path in that vertical requires Send. This trait
preserves that proof rather than spending it.
Required Methods§
fn bind(&self, local: SocketAddr) -> Result<Self::Socket>
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".