SRT & SRTLA Protocol
Summary
SRTLA (SRT Link Aggregation) is a UDP-based protocol that sits in front of an SRT (Secure Reliable Transport) server, enabling a single SRT session to be transported across multiple network links simultaneously (cellular bonding for IRL streaming). GoLiveBro’s relay infrastructure uses a custom fork of the SRTLA receiver (ghcr.io/michaelpentz/srtla-receiver) that adds per-connection byte/packet counters, an HTTP stats server (port 5080), and optional ASN carrier identification via IPinfo Lite mmdb. A full clean-room protocol specification was written on 2026-04-07 to document the wire format, handshake, keepalive, ACK mechanism, forwarding behavior, and stats API.
The relay operates as a transparent UDP proxy: it accepts SRTLA packets from multiple client connections on a single UDP port (5000), aggregates them into connection groups, and forwards them to a downstream SRT server over a single UDP socket. The protocol uses a 3-phase registration handshake (REG1/REG2/REG3) with 128-byte random client IDs and 128-byte random server IDs forming a 256-byte group ID. Stream identification uses SRT stream IDs extracted from handshake TLV extensions in the format live_{stream_token} (publish) and play_{stream_token} (viewer pull).
The stream slot system, implemented in March 2026, extends this into a multi-connection model. Each user can manage multiple concurrent relay connections through named, numbered slots stored in the user_stream_slots table. Slots are server-side constructs tied to the user’s account, with entitlement gating via max_concurrent_conns from the plan tier. BYOR (Bring Your Own Relay) connections bypass the slot system entirely since they have no server-side state.
Timeline
- 2026-03-05: Relay E2E telemetry validated. Aggregate SLS stats API polling (port 8090, every 2s) and IPC round-trip (Start, Provisioning, Active, Stop, Stopped) confirmed working via IRL Pro bonded stream.
- 2026-03-20: MetricsCollector background thread completed. Stats polling moved off OBS render thread. Start()/Stop()/PollLoop() verified. Snapshot push on connect/disconnect, relay_host_masked, not_found for unknown stream IDs.
- 2026-03-22: Stream slot system implemented (commits
b706153,c70efe7,0e933aa).user_stream_slotstable created with(user_id, slot_number)primary key, label column, and API endpoints for list (GET /api/v1/stream-slots) and rename (PUT /api/v1/stream-slots/{slot_number}). - 2026-04-07: SRTLA protocol specification v1.0 written as clean-room reference. Documented all packet types, wire formats, handshake phases, keepalive behavior, ACK batching, forwarding rules, group lifecycle, rate limiting, CIDR allowlist, stream ID extraction from SRT handshake TLV extensions, and HTTP stats API.
Current State
The SRTLA receiver runs as part of the Docker relay stack on each relay node. The full packet classification and processing pipeline is:
Packet types and their hex identifiers:
0x9000SRTLA Keepalive (bidirectional, echoed verbatim, not forwarded to SRT)0x9100SRTLA ACK (44 bytes, batch of 10 sequence numbers, per-connection scope)0x9200SRTLA REG1 (258 bytes, group creation request with 128-byte client ID)0x9201SRTLA REG2 (258 bytes, used bidirectionally for group/connection registration)0x9202SRTLA REG3 (2 bytes, connection registration confirmation)0x9210/0x9211/0x9212REG_ERR/REG_NGP/REG_NAK (2-byte error responses)- SRT control packets (bit 15 set): handshake
0x8000, ACK0x8002, NAK0x8003, shutdown0x8005 - SRT data packets (bit 15 clear): first 4 bytes contain 31-bit sequence number
Forwarding behavior:
- Client-to-server: All SRT packets forwarded unchanged to downstream SRT server via lazily-created UDP socket. SRTLA keepalives echoed back but not forwarded.
- Server-to-client: SRT ACK packets (
0x8002) broadcast to ALL connections in the group. All other packets sent only to the most recently active connection (last_addr).
Capacity limits (defaults): 200 max concurrent groups, 16 max connections per group. Connection timeout 10 seconds, group timeout 10 seconds, cleanup runs every 3 seconds.
Stats API (port 5080): Returns JSON with groups[] containing total_bytes, stream_id, and connections[] with addr, bytes, pkts, share_pct, last_ms_ago, uptime_s, and optional asn_org. Bearer token authentication with constant-time comparison. Also supports DELETE /groups/{stream_id} to force-disconnect a group.
Stream slots: Active with per-user numbered slots (1-based), user-defined labels, and API-driven management. Managed connections map to slots via connection_id + slot_number. The relay/start endpoint accepts stream_slot alongside connection_id and region_preference.
Key Decisions
- 2026-03-22: Stream slots are server-side constructs, not client-side. Stored in
user_stream_slotswith(user_id, slot_number)primary key. Slots persist across session stop/start. BYOR connections do not use stream slots. - 2026-04-07: SRTLA ACK uses a 4-byte type header (
0x91000000big-endian) unlike REG packets which use 2-byte headers. The encoding ishtobe32(SRTLA_TYPE_ACK << 16). Implementations may detect by checking either the first 2 bytes (0x9100) or the full 4-byte word. - 2026-04-07: SRT ACK packets are broadcast to all connections in a group (unlike NAK which goes only to
last_addr). Broadcasting NAK to all connections is documented as a recommended improvement for retransmission reliability when the original link is degraded. - 2026-04-07: Stream ID extraction from SRT handshake uses TLV extension type 5 (
SRT_CMD_SID). The data is encoded as big-endian 32-bit words that must be byte-swapped per-word and read as sequential ASCII characters. - 2026-04-07: Rate limiting uses per-source-IP registration throttling (default 5 registrations per 60-second sliding window). Exceeding the limit results in silent packet drop (no error response). Stale entries purged after 2x the rate window.
Gotchas & Known Issues
- SRT minimum packet length: Any non-SRTLA packet shorter than 16 bytes is silently discarded. This is the
SRT_MIN_LENconstant. - REG1/REG2 exact size requirement: Both must be exactly 258 bytes. Packets of other sizes with the correct type value are rejected.
- Stream ID byte-swap complexity: The SRT stream ID in handshake TLV extensions requires per-32-bit-word byte swapping from big-endian to host byte order, then reading the resulting bytes sequentially. On little-endian machines, the byte at the lowest address of the native word corresponds to what was the highest-order byte in big-endian.
- Group ID comparison must be constant-time: Validation of the 256-byte group ID during connection registration (REG2) requires constant-time comparison to prevent timing attacks.
- SRTLA extension types (
0xA000,0xA001): These are IRLToolkit-specific client IP request/response extensions. They are optional and not required for basic SRTLA operation. - Per-link telemetry pending: Per-link relay telemetry in the OBS dock requires the
srtla_recfork to expose per-link metadata. Test case TC-RELAY-002 is still pending validation. - IRL Pro bonding mode: Must use SRTLA mode, not SRT with bonding toggle. Enabling the built-in “Connection Bonding Service” routes through IRL Toolkit proxies and will fail with a private relay.
- SLS management API path: The API on port 3000 uses
/api/stream-ids(not/api/v1/). API key stored in/opt/srtla-receiver/data/.apikeyon the relay node. - DNS records must be DNS-only: Cloudflare proxy cannot be enabled for relay DNS records because SRT/SRTLA uses UDP which cannot go through Cloudflare’s proxy.
- Multi-connection relay test gap: TC-CONN-001 (two simultaneous BYOR connections with independent telemetry) and TC-CONN-002 (connection persistence across OBS restarts) are not yet validated.
Open Questions
- When will per-link relay telemetry (TC-RELAY-002) be validated with the
srtla_recfork exposing per-link metadata? - Should SRT NAK packets be broadcast to all connections (like ACKs) to improve retransmission reliability? The spec documents this as a recommended improvement but it is not implemented.
- How should the stats API handle multi-viewer scenarios where more than one OBS instance pulls from the same
play_{token}stream? - What is the upgrade path for the SLS Management API from port 3000 (current) to a more integrated management interface?
- Should the CIDR allowlist feature be enabled in production to restrict which IPs can register SRTLA connections?