pub struct UdpServerTransport { /* private fields */ }std and non-WebAssembly only.Expand description
Per-session server transport. The listener’s demux task reassembles inbound datagrams and pushes
the inner frames to rx; outbound frames are enveloped and sent to the captured peer from
send_socket. A server migration (migrate_to) swaps send_socket to a
freshly-bound local socket (so the client sees a new s2c source) and spawns a recv loop on it
that feeds the SAME rx channel via tx, so the client’s c2s frames are delivered transparently
once it switches its send target — while the listener demux keeps feeding rx on the old address
during the overlap.
Implementations§
Source§impl UdpServerTransport
impl UdpServerTransport
pub fn new( socket: Arc<UdpSocket>, peer: SocketAddr, cid: ConnId, tx: Sender<(Bytes, SocketAddr)>, rx: Receiver<(Bytes, SocketAddr)>, ) -> Self
Sourcepub async fn migrate_to(
&self,
new_local_addr: SocketAddr,
) -> Result<(), CoreError>
pub async fn migrate_to( &self, new_local_addr: SocketAddr, ) -> Result<(), CoreError>
Migrate the server’s send path to a fresh local socket (the server-side mirror of
the client’s UdpClientTransport::migrate_to). Binds a new unconnected socket,
swaps it in as the active send socket (so subsequent server→client datagrams egress
the new local address — the client sees a new s2c source and follows it), and spawns
a recv loop on it that reassembles datagrams and forwards complete frames into the
SAME inbound channel recv_bytes reads. The listener demux keeps feeding that channel
on the old (listen) address during the overlap, so c2s never drops; once the client
switches its send target to the new address (path validation, a later step), its
frames arrive on the new socket and flow through transparently.
A bind failure returns Err WITHOUT touching the active send socket — a server
migration to an invalid address never tears the session down (best-effort, like the
client side). Typed core; the SocketAddr-free SessionTransport::migrate_server
trait entry parses a String and delegates here.
Trait Implementations§
Source§impl Drop for UdpServerTransport
impl Drop for UdpServerTransport
Source§impl SessionTransport for UdpServerTransport
impl SessionTransport for UdpServerTransport
Source§async fn migrate_server(&self, local_addr: String) -> Result<(), CoreError>
async fn migrate_server(&self, local_addr: String) -> Result<(), CoreError>
SocketAddr-free trait entry for server-side migration. Parses the new local bind
address and delegates to the typed migrate_to. A malformed
address is a clean Err that leaves the session on its existing send socket
(best-effort, never fatal).
Source§async fn send_bytes(&self, data: &[u8]) -> Result<(), CoreError>
async fn send_bytes(&self, data: &[u8]) -> Result<(), CoreError>
Source§async fn recv_bytes(&self) -> Result<Bytes, CoreError>
async fn recv_bytes(&self) -> Result<Bytes, CoreError>
Bytes is
a refcounted view over an opaque buffer; subsequent clone()s
are cheap.Source§fn confirm_authenticated_source(&self)
fn confirm_authenticated_source(&self)
PATH_CHALLENGE target) is only ever an AEAD-authenticated source, so a
spoofed CID-matched datagram (which never decrypts) cannot clobber the candidate slot
and misdirect / stall a legitimate migration. SocketAddr-free — the address stays inside
the concrete transport. Default no-op for transports without migration.Source§fn has_migration_candidate(&self) -> bool
fn has_migration_candidate(&self) -> bool
true; stream
transports (TCP / WebSocket / WASI / Embedded) have no migration and use
the default false. Deliberately SocketAddr-free so the generic data
pump that calls it stays no_std-clean (std::net::SocketAddr does not
exist in core/alloc); the candidate address is held inside the
concrete transport.Source§async fn send_to_candidate(&self, data: &[u8]) -> Result<bool, CoreError>
async fn send_to_candidate(&self, data: &[u8]) -> Result<bool, CoreError>
data — an already-encrypted PATH_VALIDATION challenge built by the
session — to the transport’s internally-tracked candidate source, distinct
from the established peer, under the transport’s own anti-amplification cap
(RFC 9000 §8.2). Returns Ok(true) if a candidate existed and the send was
within budget, Ok(false) otherwise (no candidate, or the 3× cap was hit).
Default (non-address transports): a no-op Ok(false). The candidate
address never crosses this boundary, keeping the trait no_std-safe.Source§fn promote_candidate(&self) -> bool
fn promote_candidate(&self) -> bool
true if a candidate
was promoted. Default no-op (false) for transports without migration.
SocketAddr-free — the address is internal to the concrete transport.Source§fn set_frame_phase(&self, phase: FramePhase)
fn set_frame_phase(&self, phase: FramePhase)
FramePhase, adjusting the receive
frame-size cap (WIRE-001). Default no-op — transports that do not
length-prefix / buffer, or are inherently bounded, need not implement it.
Called once by the session machinery at the handshake → data-pump
boundary. Adding this defaulted method is source-compatible for every
existing impl.Source§fn set_outbound_cid(&self, cid: [u8; 8])
fn set_outbound_cid(&self, cid: [u8; 8])
current_outbound_cid() (the rotating CID_0), switching the
transport off the bootstrap ConnId onto the chain. Default no-op —
socket-routed transports (TCP / WebSocket / WASI / Embedded) carry no
on-wire CID and ignore it. Source-compatible for every existing impl.Source§fn migrate(
&self,
_local_addr: String,
) -> impl Future<Output = Result<(), CoreError>> + Send
fn migrate( &self, _local_addr: String, ) -> impl Future<Output = Result<(), CoreError>> + Send
String (parsed
inside the concrete native transport) so the
trait stays SocketAddr-free and no_std-clean — std::net::SocketAddr does
not exist in core/alloc. Best-effort: a parse / bind / connect failure
returns Err and the session is expected to keep running on its existing
socket — migration never tears it down. Default no-op Ok(()) for transports
without migration (TCP / WebSocket / WASI / Embedded / the in-memory test
pipe); only the native UDP client implements it.