flare_mlake · API · udp

flare.udp.socket

UDP socket: connectionless datagrams.

UdpSocket wraps a RawSocket in SOCK_DGRAM mode and exposes send_to / recv_from operations. Use bind() for a receiving socket and unbound() for a send-only socket.

Platform notes:

  • Maximum UDP payload: 65507 bytes (65535 − 8-byte UDP header − 20-byte IP header). Larger datagrams must be rejected by the caller.
  • SO_BROADCAST must be explicitly enabled to send to broadcast addresses (e.g. 255.255.255.255).

Structs

DatagramTooLarge

struct DatagramTooLarge

Raised when a UDP datagram exceeds the maximum allowed payload size.

Fields: size: The datagram size in bytes that was rejected. max_size: The platform maximum (65507 bytes).

Example:

raise DatagramTooLarge(70000)

Implements Copyable, Movable, Writable

Fields
size: Int
max_size: Int

__init__

def __init__(out self, size: Int, max_size: Int = Int(65507))

Initialise a DatagramTooLarge error.

Args
size: The requested datagram size.
max_size: The allowed maximum. Defaults to 65507.

write_to

def write_to[W: Writer](self, mut writer: W)

Write the error description to writer.

Args
writer: Destination writer.

UdpSocket

struct UdpSocket

A UDP socket for sending and receiving datagrams.

UdpSocket is Movable but not Copyable — a socket file descriptor cannot be shared without tracking both copies.

Use bind() to receive datagrams from any sender, or unbound() to create a send-only socket that the OS assigns a source port to.

Thread safety: Not thread-safe .

Example:

from flare.udp import UdpSocket
from flare.net import SocketAddr

# Receiver
var recv = UdpSocket.bind(SocketAddr.localhost(5000))
var buf = List[UInt8]()
buf.resize(1024, 0)
var (n, from_addr) = recv.recv_from(Span[UInt8, _](buf))
print("received", n, "bytes from", String(from_addr))

# Sender
var sender = UdpSocket.unbound()
sender.send_to("hello".as_bytes(), SocketAddr.localhost(5000))

Implements Movable

__init__

def __init__(out self, var socket: RawSocket, local: SocketAddr)

Wrap an existing RawSocket (internal use only).

Safety: The caller must not use socket after this constructor.

Args
socket: An open UDP socket (ownership transferred).
local: The bound address; use SocketAddr(IpAddr.unspecified(), 0) for an unbound socket.

__deinit__

def __deinit__(deinit self)

bind

def bind(addr: SocketAddr, reuse_port: Bool = False) -> Self

Create a UDP socket bound to addr.

After this call, recv_from() will receive datagrams sent to the bound address.

Example:

var s = UdpSocket.bind(SocketAddr.localhost(5000))
Args
addr: The local address to bind. Use port 0 for an OS-assigned ephemeral port.
reuse_port: Set SO_REUSEPORT first, so several sockets of this user can bind the port and the kernel spreads flows across them by 4-tuple (a multi-worker server).

Raises AddressInUse: If the port is already in use. NetworkError: For any other OS bind error.

unbound

def unbound(ipv6: Bool = False) -> Self

Create a send-only UDP socket without binding to a specific port.

The OS assigns an ephemeral source port on the first send_to(). ipv6 picks an AF_INET6 socket, needed to send to IPv6 destinations.

Example:

var s = UdpSocket.unbound()
var n = s.send_to("hello".as_bytes(), SocketAddr.localhost(5000))

Raises NetworkError: If socket(2) fails.

__enter__

def __enter__(var self) -> Self

Transfer ownership of self into the with block.

send_to

def send_to(self, data: Span[UInt8], addr: SocketAddr) -> Int

Send a datagram to addr.

Example:

var n = s.send_to("hello".as_bytes(), SocketAddr.localhost(9000))
Args
data: The payload bytes to send.
addr: The destination socket address.

Raises DatagramTooLarge: If len(data) > 65507. NetworkError: For any OS send error.

try_recv_from

def try_recv_from(mut self, buf: Span[UInt8]) -> Tuple[Int, SocketAddr]

Non-blocking recv_from via MSG_DONTWAIT.

Identical to :meth:recv_from but never blocks: raises :class:Timeout immediately when the socket queue is empty (EAGAIN / EWOULDBLOCK). Used to drain a burst of queued datagrams in one reactor tick without touching SO_RCVTIMEO per call.

recv_from

def recv_from(mut self, buf: Span[UInt8]) -> Tuple[Int, SocketAddr]

Receive a datagram, returning the byte count and sender address.

Blocks until a datagram arrives or a timeout expires.

Example:

var buf = List[UInt8]()
buf.resize(1024, 0)
var (n, sender) = s.recv_from(Span[UInt8, _](buf))
print("got", n, "bytes from", String(sender))
Args
buf: Destination span; at most len(buf) bytes are written. For UDP, this should be large enough for the expected datagram (up to 65507 bytes).

Raises Timeout: If a recv timeout was set and expired. NetworkError: For any other OS error.

set_recv_timeout

def set_recv_timeout(self, ms: Int)

Set a receive timeout via SO_RCVTIMEO.

After the timeout expires, recv_from() raises Timeout.

Args
ms: Timeout in milliseconds. 0 disables the timeout.

Raises NetworkError: If setsockopt(2) fails.

set_recv_buffer

def set_recv_buffer(self, bytes: Int)

Request a kernel receive-buffer size via SO_RCVBUF.

The kernel doubles the request and clamps it to net.core.rmem_max; the effective size may be smaller. A multi-MB buffer absorbs datagram bursts so the kernel does not drop packets between reactor ticks under load.

Args
bytes: Requested receive-buffer size in bytes.

Raises NetworkError: If setsockopt(2) fails.

set_send_buffer

def set_send_buffer(self, bytes: Int)

Request a kernel send-buffer size via SO_SNDBUF.

Args
bytes: Requested send-buffer size in bytes.

Raises NetworkError: If setsockopt(2) fails.

set_ecn

def set_ecn(self, codepoint: Int)

Mark outgoing datagrams with the ECN codepoint (0 none, 2 ECT(0), 1 ECT(1), 3 CE; RFC 3168) and deliver received datagrams' codepoints to :meth:flare.udp.BatchReceiver.ecn. Linux only; a no-op elsewhere.

Raises NetworkError: If setsockopt(2) fails.

set_broadcast

def set_broadcast(self, enabled: Bool)

Enable or disable sending to broadcast addresses.

Must be enabled before send_to() can send to 255.255.255.255 or a subnet broadcast (e.g. 192.168.1.255).

Args
enabled: True to allow broadcast sends.

Raises NetworkError: If setsockopt(2) fails.

local_addr

def local_addr(self) -> SocketAddr

Return the local address the socket is bound to.

fd

def fd(self) -> Int

Return the underlying socket file descriptor.

Exposed for the batched-I/O helpers in flare.udp.batch (recvmmsg / sendmmsg / GSO) which operate on the raw fd. Do not close it directly -- UdpSocket owns its lifetime.

close

def close(mut self)

Close the socket. Idempotent.

Aliases

comptime UDP_MAX_PAYLOAD = Int(65507)