Implements WS_RELAY_SPEC.md: relay handles both QUIC and WebSocket clients
in shared rooms, eliminating the wzp-web bridge server.
Room abstraction (room.rs):
- New ParticipantSender enum: Quic(transport) | WebSocket(mpsc::Sender)
- send_raw() sends PCM bytes to either transport type
- join_ws() convenience method for WS clients
- Forwarding loops handle mixed QUIC+WS rooms:
QUIC→QUIC: send_media (trunked if enabled)
QUIC→WS: send_raw payload bytes
WS→QUIC: send_raw wraps in MediaPacket
WS→WS: send_raw binary
WebSocket handler (ws.rs):
- GET /ws/{room} → WebSocket upgrade via axum
- Auth: first msg {"type":"auth","token":"..."} → validates against FC
- mpsc channel bridges room fan-out to WS binary frames
- Session + presence lifecycle matches QUIC path
- Optional static file serving via --static-dir (tower-http ServeDir)
Config: --ws-port 8080, --static-dir ./static
Proto: MediaHeader::default_pcm() for WS→QUIC wrapping
63 relay + 54 proto tests passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
68 lines
2.6 KiB
Rust
68 lines
2.6 KiB
Rust
//! Relay daemon configuration.
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use std::net::SocketAddr;
|
|
|
|
/// Configuration for the relay daemon.
|
|
#[derive(Clone, Debug, Serialize, Deserialize)]
|
|
pub struct RelayConfig {
|
|
/// Address to listen on for incoming connections (client-facing).
|
|
pub listen_addr: SocketAddr,
|
|
/// Address of the remote relay (for the lossy inter-relay link).
|
|
/// If None, this relay is the destination-side relay.
|
|
pub remote_relay: Option<SocketAddr>,
|
|
/// Maximum concurrent sessions.
|
|
pub max_sessions: usize,
|
|
/// Jitter buffer target depth in packets.
|
|
pub jitter_target_depth: usize,
|
|
/// Jitter buffer maximum depth in packets.
|
|
pub jitter_max_depth: usize,
|
|
/// Logging level (trace, debug, info, warn, error).
|
|
pub log_level: String,
|
|
/// featherChat auth validation URL (e.g., "https://chat.example.com/v1/auth/validate").
|
|
/// If set, clients must present a valid token before joining rooms.
|
|
pub auth_url: Option<String>,
|
|
/// Port for the Prometheus metrics HTTP endpoint (e.g., 9090).
|
|
/// If None, the metrics endpoint is disabled.
|
|
pub metrics_port: Option<u16>,
|
|
/// Peer relay addresses to probe for health monitoring.
|
|
/// Each target gets a persistent QUIC connection sending 1 Ping/s.
|
|
#[serde(default)]
|
|
pub probe_targets: Vec<SocketAddr>,
|
|
/// Enable mesh mode: each relay probes all configured targets concurrently.
|
|
/// Discovery is manual via multiple --probe flags; this flag signals intent.
|
|
#[serde(default)]
|
|
pub probe_mesh: bool,
|
|
/// Enable trunk batching for outgoing media in room mode.
|
|
/// When true, packets destined for the same receiver are accumulated into
|
|
/// [`TrunkFrame`]s and flushed every 5 ms (or when the batcher is full),
|
|
/// reducing per-packet QUIC datagram overhead.
|
|
#[serde(default)]
|
|
pub trunking_enabled: bool,
|
|
/// Port for the WebSocket listener (browser clients connect here).
|
|
/// If None, WebSocket support is disabled.
|
|
pub ws_port: Option<u16>,
|
|
/// Directory to serve static files from (HTML/JS/WASM for web clients).
|
|
pub static_dir: Option<String>,
|
|
}
|
|
|
|
impl Default for RelayConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
listen_addr: "0.0.0.0:4433".parse().unwrap(),
|
|
remote_relay: None,
|
|
max_sessions: 100,
|
|
jitter_target_depth: 50,
|
|
jitter_max_depth: 250,
|
|
log_level: "info".to_string(),
|
|
auth_url: None,
|
|
metrics_port: None,
|
|
probe_targets: Vec::new(),
|
|
probe_mesh: false,
|
|
trunking_enabled: false,
|
|
ws_port: None,
|
|
static_dir: None,
|
|
}
|
|
}
|
|
}
|