UDP services: the minimal driver of the connectionless world
UDP has no connections, no handshakes, no ordering — and XServer's driver accordingly converges to a single callback. Heartbeats, discovery protocols and log collection are its territory.
Overview
24.1 Intro
UDP's semantics are "every datagram is self-contained": no connection state, no retransmission, no ordering. XServer's udp driver faithfully mirrors that — bind the port, hand you every arriving datagram together with its source address, done. Session concepts (if any) are carried by the application inside the datagram payload.
24.2 One callback
static void EventDgram(XS_HostInfo* pHost, xnetudp* pUdp,
const xnetudpmessage* pMsg)
{
/* pMsg fields (xrt_decl.h, verbatim):
* Remote : source address (borrowed in the callback)
* Data/Size : payload and length
* Flags : XNET_UDP_MESSAGE_TRUNCATED (truncation flag) etc.
* Meta : datagram meta info */
if ( pMsg->Flags & XNET_UDP_MESSAGE_TRUNCATED ) {
/* the datagram exceeded the receive buffer and was truncated — drop or log by protocol */
return;
}
(void)xrtNetUdpSendTo(pUdp, &pMsg->Remote, "ack", 3);
}
What just happened: each datagram fires one callback; every datagram takes the current generation lease through the listener slot — during hot reloads, datagram-to-generation attribution is exactly as precise as TCP's (reload_matrix covers UDP bursts with closed peers).
24.3 The send model
- Sending is entirely the script's business:
xrtNetUdpSendTo(pUdp, target address, data, length)— reply to the source or send to any third-party address (forwarding/notification scenarios) - Convert source addresses to text with the xrt address-family tools (for logging / debugging)
- One send = one datagram — application-layer fragmentation and reassembly (if needed) is yours to define
- recv_limit caps at 65535 (ch. 07) — the natural per-datagram ceiling
24.4 Platform details
A Windows behavior worth knowing: sending UDP to an already-closed port may elicit ICMP Port Unreachable from the peer's stack, and Windows surfaces that ICMP as an error on your next send/receive — showing up as "after sending to one unrelated address, my own sends/receives mysteriously fail". XServer implements ICMP reset isolation for exactly this (a dedicated local patch in the version log): ICMP-triggered resets are quarantined and never splash onto later datagrams. reload_matrix's UDP case covers this platform behavior specifically.
24.5 Contract
- Borrowing: pMsg (incl. Remote/Data) is valid inside the callback — copy any field you need to keep before forwarding.
- Sending: all sends go through xrtNetUdpSendTo yourself; UDP guarantees datagram boundaries (content integrity is your check).
- Generations: each datagram takes the current lease — new datagrams enter the new generation during reloads, semantics identical to TCP.
Common mistakes
- Symptom
- A protocol written assuming ordering and sessions scrambles its state machine after real packet loss/reordering.
- Cause
- UDP guarantees neither delivery nor order — build sessions and retransmission yourself (sequence numbers + ACK) or switch to TCP.
- Symptom
- Sporadic half-datagram processing; checksum failures that won't reproduce.
- Cause
- Datagrams exceeding the receive cap get flagged — skipping the check treats a truncated remnant as a whole packet.
Exercises
Reply "PONG" to "PING"; drop everything else.
Implement a mini reliable protocol at the application layer (seq + ACK + retransmission; a window of 1 suffices).
Implement multicast/broadcast discovery: clients broadcast DISCOVER; the server unicasts back its HTTP port.
Summary
| Point | Conclusion |
|---|---|
| Callback surface | only EventDgram; every datagram carries source address and flags |
| Sending | xrtNetUdpSendTo, all yours; reply or forward to any address |
| Limits | recv_limit ≤65535; the TRUNCATED flag must be checked |
| Platform | Windows ICMP resets isolated; reliability and ordering are yours |
| Generations | per-datagram current lease; reload semantics identical to TCP |
- xrt reference · udp — the complete datagram send/receive and address-family toolset