### Clone Repository and Navigate Source: https://github.com/openpacketloss/openpacketloss-server/blob/main/README.md Clone the OpenPacketLoss-Server repository and navigate into the project directory. Ensure you have Rust installed. ```bash git clone https://github.com/openpacketloss/OpenPacketLoss-Server.git cd openpacketloss-server ``` -------------------------------- ### Quick Start Local Server Deployment Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Clones the repository, navigates to the directory, and runs the server in release mode. The first run automatically creates a default .env configuration file. ```bash git clone https://github.com/openpacketloss/OpenPacketLoss-Server.git cd openpacketloss-server # First run: auto-creates .env with defaults, then starts the server cargo run --release # Server output: # INFO openpacketloss_server: Created default config file: .env # INFO openpacketloss_server: === Server Configuration === # INFO openpacketloss_server: Platform Mode: SelfHosted (Self-hosted with infinite test support) # INFO openpacketloss_server: HTTP Port: 8080 # INFO openpacketloss_server: STUN Server: Enabled on port 3478 (UDP) # INFO openpacketloss_server: Max Connections: 500 # INFO openpacketloss_server: ============================ # INFO openpacketloss_server: Server listening on 0.0.0.0:8080 # INFO openpacketloss_server: STUN server listening on 0.0.0.0:3478 ``` -------------------------------- ### Monitor Server Connections with Alerting Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt This example demonstrates how to poll the server's health endpoint every 10 seconds and use a Python script to calculate and display the connection utilization percentage, alerting if it exceeds 80% capacity. ```bash watch -n 10 'curl -s http://localhost:8080/health | \ python3 -c "import sys,json; d=json.load(sys.stdin); \ pct=d[\"total_connections\"]/d[\"max_connections\"]*100; \ print(f\"Connections: {d[\"total_connections\"]}/{d[\"max_connections\"]} ({pct:.1f}%) | Uptime: {d[\"uptime_seconds\"]}s\")"' ``` -------------------------------- ### Get Server Health Status Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt This command retrieves the current health status of the OpenPacketLoss server, including active connections and uptime. It's useful for monitoring and load balancing. ```bash curl http://localhost:8080/health ``` -------------------------------- ### run_stun_server() Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Initializes and runs a lightweight STUN server as a background Tokio task. It listens for UDP packets and responds to RFC 5389 Binding Requests, enabling clients to discover their public IP addresses. ```APIDOC ## `run_stun_server()` — Lightweight Built-in STUN Server Listens for UDP packets on the given address and responds to RFC 5389 STUN Binding Requests with an XOR-MAPPED-ADDRESS response. Handles only IPv4 STUN Binding Requests (`message type 0x0001`) and silently ignores non-STUN traffic. Runs as a long-lived async task spawned alongside the HTTP server. ```rust use openpacketloss_server::run_stun_server; // Spawned as a background Tokio task — runs forever until the process exits tokio::spawn(async move { if let Err(e) = run_stun_server("0.0.0.0:3478").await { eprintln!("STUN server failed: {}", e); } }); // Verify with a STUN client: // $ stunclient your-server.example.com 3478 // Binding test: success // Local address: 192.168.1.50:54321 // Mapped address: 203.0.113.42:54321 // Or disable entirely by setting STUN_URL=none in .env ``` ``` -------------------------------- ### Load and Validate Server Configuration from Environment Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Reads server parameters from environment variables, applies defaults, and validates constraints. Returns an error if any value is invalid. Ensure environment variables are set before calling. ```rust use openpacketloss_server::ServerConfig; // All config comes from environment variables; set them before calling from_env() std::env::set_var("PORT", "9090"); std::env::set_var("STUN_PORT", "3479"); std::env::set_var("STUN_URL", "auto"); // auto | stun:host:port | none std::env::set_var("PLATFORM_MODE", "self"); // self | web std::env::set_var("MAX_CONNECTIONS", "200"); std::env::set_var("MAX_CONNECTIONS_PER_IP", "5"); std::env::set_var("ICE_GATHERING_TIMEOUT_SECS", "3"); std::env::set_var("OVERALL_REQUEST_TIMEOUT_SECS", "30"); std::env::set_var("NAT_1TO1_IP", "203.0.113.42"); // explicit public IP for NAT/Docker std::env::set_var("ICE_PORT_MIN", "10000"); // restrict WebRTC UDP port range std::env::set_var("ICE_PORT_MAX", "10100"); match ServerConfig::from_env() { Ok(config) => { config.log(); // Emits all settings at INFO level println!("Listening on port {}", config.port); println!("STUN enabled: {}", config.stun_enabled); println!("ICE port range: {:?}", config.ice_port_range); // Some((10000, 10100)) } Err(e) => { eprintln!("Config error: {}", e); // e.g. "OVERALL_REQUEST_TIMEOUT_SECS (3) must be greater than ICE_GATHERING_TIMEOUT_SECS (3)" std::process::exit(1); } } ``` -------------------------------- ### ServerConfig::from_env() Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Loads and validates server configuration from environment variables. It applies defaults for missing values and checks constraints, returning an error if validation fails. ```APIDOC ## `ServerConfig::from_env()` — Load and Validate Configuration Reads all server parameters from environment variables (or `.env` file), applies defaults for any missing values, validates constraints (e.g., `OVERALL_REQUEST_TIMEOUT_SECS` must exceed `ICE_GATHERING_TIMEOUT_SECS`), and returns a fully validated `ServerConfig`. Returns `Err(String)` with a descriptive message if any value is invalid. ```rust use openpacketloss_server::ServerConfig; // All config comes from environment variables; set them before calling from_env() std::env::set_var("PORT", "9090"); std::env::set_var("STUN_PORT", "3479"); std::env::set_var("STUN_URL", "auto"); // auto | stun:host:port | none std::env::set_var("PLATFORM_MODE", "self"); // self | web std::env::set_var("MAX_CONNECTIONS", "200"); std::env::set_var("MAX_CONNECTIONS_PER_IP", "5"); std::env::set_var("ICE_GATHERING_TIMEOUT_SECS", "3"); std::env::set_var("OVERALL_REQUEST_TIMEOUT_SECS", "30"); std::env::set_var("NAT_1TO1_IP", "203.0.113.42"); // explicit public IP for NAT/Docker std::env::set_var("ICE_PORT_MIN", "10000"); // restrict WebRTC UDP port range std::env::set_var("ICE_PORT_MAX", "10100"); match ServerConfig::from_env() { Ok(config) => { config.log(); // Emits all settings at INFO level println!("Listening on port {}", config.port); println!("STUN enabled: {}", config.stun_enabled); println!("ICE port range: {:?}", config.ice_port_range); // Some((10000, 10100)) } Err(e) => { eprintln!("Config error: {}", e); // e.g. "OVERALL_REQUEST_TIMEOUT_SECS (3) must be greater than ICE_GATHERING_TIMEOUT_SECS (3)" std::process::exit(1); } } ``` ``` -------------------------------- ### build_webrtc_api() Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Constructs a `webrtc::api::API` instance, configured with options such as disabling mDNS, setting up NAT 1-to-1 IP mapping, and restricting ICE UDP port ranges based on the provided `ServerConfig`. ```APIDOC ## `build_webrtc_api()` — Construct the WebRTC API Instance Builds a configured `webrtc::api::API` with mDNS disabled, optional NAT 1-to-1 IP mapping (for Docker/cloud environments where the server's LAN IP differs from its public IP), and optional ICE UDP port range restrictions. The resulting `API` is shared (via `Arc`) across all peer connections created during the server's lifetime. ```rust use openpacketloss_server::{ServerConfig, build_webrtc_api}; use std::sync::Arc; let config = ServerConfig::from_env().expect("valid config"); // Builds API with: // - mDNS disabled (reduces unnecessary multicast traffic) // - NAT 1-to-1 mapping if NAT_1TO1_IP is set (e.g. running behind Docker NAT) // - ICE UDP port range limited to ICE_PORT_MIN–ICE_PORT_MAX if both are set // - Default interceptors (RTCP, NACK, etc.) registered let api = Arc::new(build_webrtc_api(&config)); // Example: restrict to 50 UDP ports for firewall compatibility // NAT_1TO1_IP=203.0.113.42 ICE_PORT_MIN=50000 ICE_PORT_MAX=50050 cargo run --release ``` ``` -------------------------------- ### Send WebRTC SDP Offer to Server Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Use this command to send a WebRTC SDP offer to the server's signaling endpoint. Ensure the SDP is valid and within size limits. The server will respond with an SDP answer and a peer connection ID. ```bash curl -X POST http://localhost:8080/webrtc/offer \ -H "Content-Type: application/json" \ -d '{ "sdp": { "type": "offer", "sdp": "v=0\r\no=- 1234567890 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\n..." } }' ``` -------------------------------- ### Run OpenPacketLoss Server Source: https://github.com/openpacketloss/openpacketloss-server/blob/main/README.md Compile and run the OpenPacketLoss server in release mode using Cargo. The server will automatically generate a default .env file on its first execution. ```bash cargo run --release ``` -------------------------------- ### ensure_config_file() Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Checks for the existence of a `.env` configuration file and creates it with default values if it's missing. This function is idempotent and ensures a configuration file is present before loading. ```APIDOC ## `ensure_config_file()` — Auto-Generate `.env` on First Run Checks whether a `.env` config file exists at the given path; if not, creates it from `DEFAULT_CONFIG_TEMPLATE` with all sensible defaults pre-filled. On Unix systems the file is created with permissions `0o600` (owner read/write only) to protect any secrets. Idempotent — safe to call on every startup. ```rust use openpacketloss_server::ensure_config_file; use std::path::Path; // Called once at startup before loading config ensure_config_file(Path::new(".env")); // If .env didn't exist, it's now created with content like: // PLATFORM_MODE=self // PORT=8080 // STUN_PORT=3478 // STUN_URL=auto // MAX_CONNECTIONS=500 // MAX_CONNECTIONS_PER_IP=10 // ICE_GATHERING_TIMEOUT_SECS=5 // OVERALL_REQUEST_TIMEOUT_SECS=30 // STALE_CONNECTION_AGE_SECS=120 // PERIODIC_CLEANUP_INTERVAL_SECS=5 // RUST_LOG=info // File permissions on Linux: -rw------- (600) ``` ``` -------------------------------- ### Docker Deployment for NAT Environments Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Runs the OpenPacketLoss server using Docker, suitable for environments behind NAT. Explicitly sets public IP and port ranges for WebRTC ICE candidates. Ensure required ports are open. ```bash # For Docker or cloud VMs behind NAT, set the public IP explicitly # so WebRTC ICE candidates advertise the correct external address docker run -e PORT=8080 \ -e STUN_PORT=3478 \ -e NAT_1TO1_IP=203.0.113.42 \ -e ICE_PORT_MIN=10000 \ -e ICE_PORT_MAX=10100 \ -e PLATFORM_MODE=self \ -e RUST_LOG=info \ -p 8080:8080 \ -p 3478:3478/udp \ -p 10000-10100:10000-10100/udp \ openpacketloss-server # Required open ports: # TCP 8080 — HTTP signaling # UDP 3478 — Built-in STUN ``` -------------------------------- ### Construct WebRTC API Instance Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Builds a configured `webrtc::api::API` instance, disabling mDNS, optionally mapping NAT 1-to-1 IPs, and restricting ICE UDP port ranges. The `API` is shared via `Arc` across all peer connections. ```rust use openpacketloss_server::{ServerConfig, build_webrtc_api}; use std::sync::Arc; let config = ServerConfig::from_env().expect("valid config"); // Builds API with: // - mDNS disabled (reduces unnecessary multicast traffic) // - NAT 1-to-1 mapping if NAT_1TO1_IP is set (e.g. running behind Docker NAT) // - ICE UDP port range limited to ICE_PORT_MIN–ICE_PORT_MAX if both are set // - Default interceptors (RTCP, NACK, etc.) registered let api = Arc::new(build_webrtc_api(&config)); // Example: restrict to 50 UDP ports for firewall compatibility // NAT_1TO1_IP=203.0.113.42 ICE_PORT_MIN=50000 ICE_PORT_MAX=50050 cargo run --release ``` -------------------------------- ### Auto-Generate .env Config File Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Checks for a `.env` file and creates it with default values if it doesn't exist. On Unix, the file is created with `0o600` permissions. This function is idempotent and safe to call on every startup. ```rust use openpacketloss_server::ensure_config_file; use std::path::Path; // Called once at startup before loading config ensure_config_file(Path::new(".env")); // If .env didn't exist, it's now created with content like: // PLATFORM_MODE=self // PORT=8080 // STUN_PORT=3478 // STUN_URL=auto // MAX_CONNECTIONS=500 // MAX_CONNECTIONS_PER_IP=10 // ICE_GATHERING_TIMEOUT_SECS=5 // OVERALL_REQUEST_TIMEOUT_SECS=30 // STALE_CONNECTION_AGE_SECS=120 // PERIODIC_CLEANUP_INTERVAL_SECS=5 // RUST_LOG=info // File permissions on Linux: -rw------- (600) ``` -------------------------------- ### Run Built-in STUN Server Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Listens for UDP packets and responds to RFC 5389 STUN Binding Requests with XOR-MAPPED-ADDRESS. Handles only IPv4 STUN Binding Requests and ignores other traffic. Runs as a background async task. ```rust use openpacketloss_server::run_stun_server; // Spawned as a background Tokio task — runs forever until the process exits tokio::spawn(async move { if let Err(e) = run_stun_server("0.0.0.0:3478").await { eprintln!("STUN server failed: {}", e); } }); // Verify with a STUN client: // $ stunclient your-server.example.com 3478 // Binding test: success // Local address: 192.168.1.50:54321 // Mapped address: 203.0.113.42:54321 // Or disable entirely by setting STUN_URL=none in .env ``` -------------------------------- ### Spawn Periodic Cleanup Loop in Rust Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Spawns a background async loop for periodic cleanup of peer connections. Ensure AppState is constructed and shared using Arc. ```rust use openpacketloss_server::{AppState, periodic_cleanup}; use std::sync::Arc; // AppState is constructed once and shared everywhere let shared_state = Arc::new(AppState { /* ... */ }); // Spawn the cleanup loop — it runs for the lifetime of the server let cleanup_state = Arc::clone(&shared_state); tokio::spawn(async move { periodic_cleanup(cleanup_state).await; // Logs: "Periodic cleanup removing N stale connections" // Then closes each RTCPeerConnection gracefully in a spawned task }); // Tune via .env: // PERIODIC_CLEANUP_INTERVAL_SECS=5 # how often to scan (default: 5s) // STALE_CONNECTION_AGE_SECS=120 # max age before forced eviction (default: 120s) ``` -------------------------------- ### Browser-side DataChannel for Packet Loss Measurement Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Client-side JavaScript for establishing a DataChannel, sending ping messages, and calculating packet loss percentages. Configure RTCPeerConnection with STUN servers and DataChannel with ordered: false and maxRetransmits: 0 for UDP-like behavior. ```javascript // Browser-side usage (compatible frontend pattern) const pc = new RTCPeerConnection({ iceServers: [{ urls: 'stun:your-server.example.com:3478' }] }); const dc = pc.createDataChannel('packetloss', { ordered: false, // No ordering — UDP-like maxRetransmits: 0 // No retransmission — drops are real drops }); let sent = 0; let receivedFromServer = 0; const startTime = Date.now(); dc.onmessage = (event) => { const msg = JSON.parse(event.data); // msg.seq — original client sequence number // msg.timestamp — original send timestamp (ms) // msg.s_rx — server's cumulative receive count (for C2S loss) receivedFromServer++; const clientToServerLoss = ((msg.seq + 1 - msg.s_rx) / (msg.seq + 1)) * 100; const serverToClientLoss = ((sent - receivedFromServer) / sent) * 100; console.log(`C→S loss: ${clientToServerLoss.toFixed(1)}% S→C loss: ${serverToClientLoss.toFixed(1)}%`); }; dc.onopen = () => { // Send 200 packets at 10ms intervals (~20 seconds test) let seq = 0; const interval = setInterval(() => { if (seq >= 200) { clearInterval(interval); return; } const msg = { seq: seq++, timestamp: Date.now() }; dc.send(JSON.stringify(msg)); sent++; }, 10); }; // Initiate signaling const offer = await pc.createOffer(); await pc.setLocalDescription(offer); const res = await fetch('http://your-server.example.com:8080/webrtc/offer', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ sdp: pc.localDescription }) }); const { sdp, pc_id } = await res.json(); console.log('PeerConnection ID:', pc_id); await pc.setRemoteDescription(sdp); ``` -------------------------------- ### Server Health Check Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt Returns the current server status, total active peer connections, the configured maximum connection limit, and server uptime in seconds. Useful for load balancer health probes and monitoring dashboards. ```APIDOC ## GET /health — Server Health Check ### Description Returns the current server status, total active peer connections, the configured maximum connection limit, and server uptime in seconds. Useful for load balancer health probes and monitoring dashboards. ### Method GET ### Endpoint /health ### Response #### Success Response (200 OK) - **status** (string) - The current status of the server (e.g., "healthy"). - **total_connections** (integer) - The number of currently active peer connections. - **max_connections** (integer) - The maximum number of allowed peer connections. - **uptime_seconds** (integer) - The server uptime in seconds. #### Response Example ```json { "status": "healthy", "total_connections": 12, "max_connections": 500, "uptime_seconds": 3842 } ``` ``` -------------------------------- ### WebRTC SDP Offer Exchange Source: https://context7.com/openpacketloss/openpacketloss-server/llms.txt The sole signaling endpoint. Accepts a WebRTC SDP offer from a browser client, creates a RTCPeerConnection, completes ICE gathering, and returns an SDP answer along with a unique peer connection ID. The connection uses ordered: false / maxRetransmits: 0 Data Channels to simulate UDP. Rate limiting is enforced both globally (total connections) and per client IP. ```APIDOC ## POST /webrtc/offer — WebRTC SDP Offer Exchange ### Description Accepts a WebRTC SDP offer from a browser client, creates a `RTCPeerConnection`, completes ICE gathering, and returns an SDP answer along with a unique peer connection ID. The connection uses `ordered: false` / `maxRetransmits: 0` Data Channels to simulate UDP. Rate limiting is enforced both globally (total connections) and per client IP. ### Method POST ### Endpoint /webrtc/offer ### Request Body - **sdp** (object) - Required - The SDP offer from the client. - **type** (string) - Required - The type of the SDP, should be "offer". - **sdp** (string) - Required - The SDP content. ### Request Example ```json { "sdp": { "type": "offer", "sdp": "v=0\r\no=- 1234567890 2 IN IP4 127.0.0.1\r\ns=-\r\nt=0 0\r\na=group:BUNDLE 0\r\n..." } } ``` ### Response #### Success Response (200 OK) - **sdp** (object) - The SDP answer from the server. - **type** (string) - The type of the SDP, should be "answer". - **sdp** (string) - The SDP content. - **pc_id** (string) - A unique identifier for the peer connection. #### Response Example ```json { "sdp": { "type": "answer", "sdp": "v=0\r\no=- 9876543210 2 IN IP4 0.0.0.0\r\n..." }, "pc_id": "550e8400-e29b-41d4-a716-446655440000" } ``` #### Error Responses - **400 Bad Request** - SDP too large (>64KB) or wrong SDP type - **429 Too Many Requests** - Per-IP connection limit exceeded - **503 Service Unavailable** - Global connection limit reached - **408 Request Timeout** - Overall handshake timeout exceeded ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.