Xirsys.Sockets.Transport.UDP (xturn_sockets v2.2.1)

View Source

UDP transport (:gen_udp) for STUN/TURN listeners and relay data paths.

What problem this solves

STUN Binding and TURN over UDP arrive as connectionless datagrams. This module wraps :gen_udp behind the Transport behaviour: bind and listen, normalize {:udp, ...} / ICMP error messages, and expose helpers for high-rate relay sockets (open_relay/2) outside the drain loop.

listen/3 opens a client-facing socket (passive until the owner arms active). open_relay/2 opens a relay socket (active-once, large buffers, ICMP error queue on Linux). IPv6 listen sockets on Linux set ipv6_v6only.

RFCs

Summary

Functions

Transfers UDP socket message delivery to pid (used for relay ingress).

Maps :udp / :udp_error messages. ICMP errors become {:icmp, info}.

Opens a relay UDP socket (active-once, 1 MiB buffers, ICMP errqueue on Linux).

Sets the don't-fragment bit. Returns {:error, :not_supported} when the OS rejects both the inet option and the raw fallback.

Sets the IPv6 flow label on socket.

Sets IPv4 TTL or IPv6 hop limit from the socket's family.

Sets IPv4 TOS on socket.

Functions

controlling_process(socket, pid)

Transfers UDP socket message delivery to pid (used for relay ingress).

Parameters

  • socket - open UDP socket
  • pid - process that will receive {:udp, ...} / {:udp_passive, ...}

handle_message(arg1, socket)

Maps :udp / :udp_error messages. ICMP errors become {:icmp, info}.

info is %{type, code, error_data, peer}. Integer error_data is passed through; destination-unreachable / packet-too-big payloads may carry an MTU.

iex> alias Xirsys.Sockets.Transport.UDP
iex> UDP.handle_message({:udp, :port, {127, 0, 0, 1}, 3478, "hi"}, :sock)
{:data, "hi", {{127, 0, 0, 1}, 3478}}
iex> UDP.handle_message({:udp_error, :sock, {:icmp, 3, 4, 1280, {{8, 8, 8, 8}, 3478}}}, :sock)
{:icmp, %{type: 3, code: 4, error_data: 1280, peer: {{8, 8, 8, 8}, 3478}}}
iex> UDP.handle_message(:other, :sock)
:ignore
iex> UDP.framing()
:datagram

open_relay(ip, opts \\ [])

@spec open_relay(
  :inet.ip_address(),
  keyword()
) :: {:ok, term()} | {:error, term()}

Opens a relay UDP socket (active-once, 1 MiB buffers, ICMP errqueue on Linux).

Parameters

  • ip - bind address
  • opts - extra open options; :port (default 0) is pulled out before merge

set_dont_fragment(socket)

@spec set_dont_fragment(term()) :: :ok | {:error, :not_supported}

Sets the don't-fragment bit. Returns {:error, :not_supported} when the OS rejects both the inet option and the raw fallback.

Parameters

  • socket - open UDP socket (IPv4 or IPv6)

set_flow_label(socket, label)

@spec set_flow_label(term(), non_neg_integer()) :: :ok | {:error, term()}

Sets the IPv6 flow label on socket.

Parameters

  • socket - open IPv6 UDP socket
  • label - 20-bit flow label

set_hop_limit(socket, ttl)

@spec set_hop_limit(term(), pos_integer()) :: :ok | {:error, term()}

Sets IPv4 TTL or IPv6 hop limit from the socket's family.

Parameters

  • socket - open UDP socket
  • ttl - hop limit / TTL

set_tos(socket, tos)

@spec set_tos(term(), non_neg_integer()) :: :ok | {:error, term()}

Sets IPv4 TOS on socket.

Parameters

  • socket - open UDP socket
  • tos - type-of-service byte