Skip to content

Latest commit

 

History

History
289 lines (191 loc) · 13.7 KB

File metadata and controls

289 lines (191 loc) · 13.7 KB

AGENTS.md

This document targets two audiences:

  1. LLMs/agents: quickly understand project structure, entry points, run flow, configuration, and risks.
  2. Human developers/operators: follow the steps to build, configure, start, and verify the service.

Project Overview

turn-rs is a TURN/STUN server implemented in Rust for WebRTC NAT traversal and media relay. It focuses on high performance and low configuration cost, and provides optional gRPC management APIs, Prometheus metrics, and Hook callbacks.

Core Capabilities

  • TURN/STUN protocol support with TCP/UDP transport.
  • Long-term credential mechanism with static users and hook-based dynamic auth.
  • Optional gRPC management API and Prometheus metrics exporter.
  • Multi-interface listeners and external address announcement.

Key Entry Points and Directories

Source Code Architecture (Modules and Responsibilities)

This section explains how the server is organized internally and how the main data flow works.

High-level runtime flow

  1. src/main.rs loads config, initializes logging, and builds the Tokio runtime.

  2. src/lib.rs start_server() constructs Statistics, a Handler, and a Service, then spawns:

Core modules

  1. src/service: TURN service core, shared state, and routing glue.
  • Service holds realm, interfaces, session manager, and handler, and creates per-connection routers.
  • ServiceHandler defines the hooks the protocol layer uses for auth and lifecycle callbacks.
  • src/service/routing.rs parses STUN/TURN messages and dispatches by method.
  1. src/service/session: Session state, allocation, permissions, and channel bindings.
  • Identifier (source + interface) is the primary session key.
  • SessionManager owns sessions, port mappings, permissions, and channel relay tables.
  • Session tracks authentication state, nonce, allocated port, channels, permissions, and expiry.
  • src/service/session/ports.rs provides PortAllocator and PortRange.
  1. src/server: Transport orchestration and cross-protocol forwarding.
  • src/server/mod.rs start_server() spawns TCP/UDP listeners per configured interface and aborts all servers if any one exits.
  • src/server/switch.rs Switch maps each session Identifier to an internal channel for forwarding relayed packets between sockets; missing destinations are dropped silently.
  • src/server/buffer.rs provides a global memory pool (Buffer) backed by a lock-free crossbeam_queue::ArrayQueue with a background task that shrinks idle buffers to avoid leaks.
  1. src/server/provider: Transport abstraction and server loop.
  • src/server/provider/mod.rs defines the ProviderServer/ProviderStream traits and ServerOptions. ProviderServer::start binds sockets, spawns per-connection tasks, routes packets, applies TCP channel-data padding, drives stats reporting, and handles idle timeout.
  • src/server/provider/udp.rs implements UdpServer/UdpSession (a single shared socket demultiplexed into per-peer channels).
  • src/server/provider/tcp.rs implements TcpServer with an optional TLS (MaybeSslStream) accept path.
  1. src/handler.rs: Implements ServiceHandler.
  • Auth flow: static credentials -> static auth secret -> optional Hook GetPassword.
  • Lifecycle events: allocation, channel bind, permission create, refresh, destroy (sent to Hook service when enabled).
  1. src/api.rs: gRPC management API and Hook client implementation.
  • TurnService exposes GetInfo/GetSession/GetSessionStatistics/DestroySession.
  • RpcHooksService maintains a client + buffered event channel to the external Hook service.
  • The protobuf definitions and generated types now live in the turn-server-sdk crate; this module consumes them via sdk::protos::*.
  1. src/codec: STUN/TURN codec and crypto.
  • Decoder differentiates STUN messages vs. ChannelData.
  • Message encoder/decoder handles attributes, integrity, and fingerprint.
  • crypto contains HMAC and password derivation helpers.
  1. src/statistics.rs: Per-session counters and reporting.
  • StatisticsReporter aggregates per-session bytes/packets and error counts.
  • Integrates with Prometheus metrics when enabled.
  1. src/prometheus.rs: HTTP metrics endpoint.
  • Exposes /metrics, tracks global + per-transport counts and allocated sessions.
  1. sdk: turn-server-sdk workspace crate (gRPC client/server utilities).
  • Owns sdk/protos/server.proto and its generated types (built via sdk/build.rs).
  • Provides TurnService client, TurnHooksServer, and password-generation helpers for integrators.
  • Consumed by the main binary through the api feature; published independently for external clients.

Design notes and key decisions

  • Long-term credentials are the primary auth model; Hook auth is optional and pluggable.
  • Port allocation is a pre-sized bitset allocator for fast random relay port selection.
  • Session tables are pre-sized HashMaps for performance under load.
  • Router validates peer addresses against local interfaces by default to reduce abuse risk.
  • Transport loop is unified with the ProviderServer/ProviderStream traits, but TCP/UDP sockets have their own implementations.
  • Read buffers come from a global, self-shrinking memory pool (server::buffer::Buffer) to reduce allocation pressure on the hot path.
  • The Switch does not require relay sends to succeed: if a destination session is gone, the packet is dropped and the entry is reclaimed.

Quick Start

Option 1: Release Binary

  1. Download the binary from GitHub Releases for your platform.
  2. Prepare a config file (see turn-server.toml).
  3. Start the server:
turn-server --config ./turn-server.toml

Option 2: Build From Source

Install the Rust toolchain, then run in the project root:

cargo build --release

The binary will be in the target/release directory.

Configuration

The config file uses TOML. Full reference: docs/configure.md.

Configuration capabilities (feature-oriented)

  • server.* defines reachability and transport surfaces: server.interfaces supports multi-NIC and multi-transport (udp/tcp) listeners, listen binds the local address, and external advertises the public address to clients behind NAT or load balancers. server.port-range limits relay port allocation, server.max-threads caps runtime workers, and server.realm is a key input for long-term credential auth.
  • server.interfaces.idle-timeout reclaims idle connection resources. Note: server.interfaces.mtu is deprecated and no longer affects relaying; it is retained only for config compatibility.
  • TLS is enabled per surface: data plane via server.interfaces.ssl.* (TCP transport only), management plane via api.ssl.*, and metrics plane via prometheus.ssl.*. This lets you secure exposed endpoints while keeping internal ones lightweight.
  • Auth strategy is defined by auth.*: auth.static-credentials provides local static users, auth.static-auth-secret enables TURN REST-style shared secrets; for dynamic auth, combine auth.enable-hooks-auth with hooks.* so an external Hook service can provide passwords and handle session events. Priority is static users first, then shared secret, then Hooks.
  • hooks.* enables external integrations for dynamic auth and lifecycle callbacks (allocation, refresh, destroy, and more). hooks.max-channel-size and hooks.timeout control backpressure and timeouts so Hooks do not impact the main data path.
  • api.* enables the gRPC management interface for querying server info, session state, statistics, and destroying sessions.
  • prometheus.* exposes Prometheus metrics (requires the prometheus feature at build time).
  • log.* controls observability output: log.level sets verbosity, log.stdout fits container or systemd aggregation, and log.file-directory enables local log retention.

Start the Server

Basic command:

turn-server --config ./turn-server.toml

For Linux systemd service, see docs/start-the-server.md.

Docker

Docker image is published on GitHub Packages. Pull and mount your config:

docker pull ghcr.io/mycrl/turn-server:latest
# Override the default config path inside the container
# Default path: /etc/turn-server/config.toml

See docs/install.md for details.

Build Features (Optional)

You can reduce the binary by compiling with specific features:

  • udp: UDP transport (default on)
  • tcp: TCP transport
  • ssl: TLS support
  • api: gRPC management API
  • prometheus: metrics exporter

Example:

cargo build --release --no-default-features --features udp,tcp

API and Hooks

The following section explains how these capabilities work and what they provide, for readers unfamiliar with TURN ecosystems.

gRPC Management API (server exposes to clients)

Purpose: allow external systems to query server status, inspect sessions, collect stats, and destroy sessions.

Protocol and fields: sdk/protos/server.proto. Core RPCs:

  • GetInfo: returns software info, uptime, listening interfaces, port capacity, and allocated ports.
  • GetSession: query a session by id, returns username, permissions, channels, allocated port, and expiry.
  • GetSessionStatistics: per-session bytes/packets and error packet counts.
  • DestroySession: terminate a session by id.

Enablement and security:

  • This endpoint has no TLS or auth by default. If exposed beyond a trusted network, enable api.ssl.*.
  • Bind address is configured by api.listen (default 127.0.0.1:3000).
  • Timeouts are configured by api.timeout.

Hook Service (server calls external system)

Purpose: dynamic authentication and event callbacks. At specific moments, turn-rs calls the external Hook service. The external service can decide whether to allow access and can record or integrate lifecycle events.

Protocol and fields: sdk/protos/server.proto. Two categories:

  1. Dynamic authentication
  • GetPassword: server asks for the password used to compute TURN message integrity.
  • Request includes username, realm, and algorithm (MD5 or SHA256).
  • Response returns password as bytes.
  1. Event callbacks
  • OnAllocatedEvent: relay allocation completed.
  • OnChannelBindEvent: channel bound.
  • OnCreatePermissionEvent: permission created.
  • OnRefreshEvent: allocation refresh/extend.
  • OnDestroyEvent: session destroyed.

Enablement and behavior:

  • Hook address is configured by hooks.endpoint, with TLS via hooks.ssl.*.
  • auth.static-credentials takes priority over Hook auth.
  • If auth.static-auth-secret is configured, the server skips Hook password lookups.
  • hooks.timeout controls request timeouts; hooks.max-channel-size limits event buffering.

Typical use cases:

  • Integrate with your account system for dynamic auth (temporary tickets, internal SSO).
  • Record session lifecycle metrics for auditing or risk analysis.

Logging and Observability

  • log.level controls log verbosity.
  • log.stdout enables or disables stdout logs.
  • log.file-directory writes logs to a daily file.
  • prometheus.listen enables the metrics endpoint (requires prometheus feature).

Security Notes

  • gRPC management endpoint has no auth/TLS by default; enable api.ssl.* or keep it in a trusted network.
  • Protect certificates, private keys, and shared secrets with filesystem permissions.

Tests and Benchmarks

  • Unit/integration tests:
cargo test
  • Benchmarks (optional):
cargo bench

Common Operations

  • Update config: edit turn-server.toml and restart the service.
  • Multi-interface: add multiple entries under server.interfaces with distinct listen/external.
  • NAT environment: set external to a public reachable address so clients receive correct candidates.

Suitable Scenarios

  • WebRTC TURN relay
  • High-throughput media forwarding with stable long-lived connections

Not Suitable Scenarios

  • Full coturn feature parity
  • Complex auth systems without a deployable Hook service

Maintenance Notes (for agents/automation)