From bfd9deffd74b849dccb825a1dbf3adda0423e46f Mon Sep 17 00:00:00 2001 From: Dan Root Date: Mon, 8 Jun 2026 09:07:08 -0500 Subject: [PATCH] expose TCPFallbackRTTThreshold and AllowUDPUnstableFallback via config (#4556) --- config-sample.yaml | 6 ++++ pkg/config/config.go | 12 ++++++++ pkg/service/roommanager.go | 58 ++++++++++++++++++++------------------ 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/config-sample.yaml b/config-sample.yaml index 7a1eece37..f264e721e 100644 --- a/config-sample.yaml +++ b/config-sample.yaml @@ -114,6 +114,12 @@ rtc: # allow_pause: true # # allows automatic connection fallback to TCP and TURN/TLS (if configured) when UDP has been unstable, default true # allow_tcp_fallback: true + # # signaling RTT (in milliseconds) below which ICE/TCP is attempted on a UDP failure; at or above it, + # # supporting clients fall back directly to TURN/TLS. 0 (default) disables the check (ICE/TCP always tried). + # # a positive value also enables allow_udp_unstable_fallback. + # tcp_fallback_rtt_threshold: 0 + # # migrate an established-but-lossy UDP connection to ICE/TCP or TURN/TLS. requires tcp_fallback_rtt_threshold > 0, default false + # allow_udp_unstable_fallback: false # # number of packets to buffer in the SFU for video, defaults to 500 # packet_buffer_size_video: 500 # # number of packets to buffer in the SFU for audio, defaults to 200 diff --git a/pkg/config/config.go b/pkg/config/config.go index 6d65973f9..68d3e8a2c 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -116,6 +116,18 @@ type RTCConfig struct { // allow TCP and TURN/TLS fallback AllowTCPFallback *bool `yaml:"allow_tcp_fallback,omitempty"` + // Signaling RTT threshold (in milliseconds) governing ICE/TCP fallback. On a UDP + // failure, ICE/TCP is attempted only while the measured signaling RTT is below this + // value; at or above it, supporting clients fall back directly to TURN/TLS. When 0 + // (the default), the RTT check is disabled and ICE/TCP is always attempted (for + // clients that support it). A positive value also gates allow_udp_unstable_fallback. + TCPFallbackRTTThreshold int `yaml:"tcp_fallback_rtt_threshold,omitempty"` + + // When enabled, an established UDP connection reporting sustained high packet loss is + // migrated to ICE/TCP or TURN/TLS. Requires tcp_fallback_rtt_threshold to be set + // (> 0). Disabled by default. + AllowUDPUnstableFallback bool `yaml:"allow_udp_unstable_fallback,omitempty"` + // force a reconnect on a publication error ReconnectOnPublicationError *bool `yaml:"reconnect_on_publication_error,omitempty"` diff --git a/pkg/service/roommanager.go b/pkg/service/roommanager.go index 65eeb5eda..9419e282e 100644 --- a/pkg/service/roommanager.go +++ b/pkg/service/roommanager.go @@ -471,34 +471,36 @@ func (r *RoomManager) StartSession( } participant, err = rtc.NewParticipant(rtc.ParticipantParams{ - Identity: pi.Identity, - Name: pi.Name, - SID: sid, - Config: &rtcConf, - Sink: responseSink, - AudioConfig: r.config.Audio, - VideoConfig: r.config.Video, - LimitConfig: r.config.Limit, - ProtocolVersion: pv, - SessionStartTime: sessionStartTime, - SessionTimer: observability.NewSessionTimer(sessionStartTime), - TelemetryListener: room.ParticipantTelemetryListener(), - Trailer: room.Trailer(), - PLIThrottleConfig: r.config.RTC.PLIThrottle, - CongestionControlConfig: r.config.RTC.CongestionControl, - PublishEnabledCodecs: enabledCodecs, - SubscribeEnabledCodecs: enabledCodecs, - Grants: pi.Grants, - Reconnect: pi.Reconnect, - Logger: pLogger, - Reporter: roomobs.NewNoopParticipantSessionReporter(), - ClientConf: clientConf, - ClientInfo: rtc.ClientInfo{ClientInfo: pi.Client}, - Region: pi.Region, - AdaptiveStream: pi.AdaptiveStream, - AllowTCPFallback: allowFallback, - TURNSEnabled: r.config.IsTURNSEnabled(), - ParticipantListener: room.LocalParticipantListener(), + Identity: pi.Identity, + Name: pi.Name, + SID: sid, + Config: &rtcConf, + Sink: responseSink, + AudioConfig: r.config.Audio, + VideoConfig: r.config.Video, + LimitConfig: r.config.Limit, + ProtocolVersion: pv, + SessionStartTime: sessionStartTime, + SessionTimer: observability.NewSessionTimer(sessionStartTime), + TelemetryListener: room.ParticipantTelemetryListener(), + Trailer: room.Trailer(), + PLIThrottleConfig: r.config.RTC.PLIThrottle, + CongestionControlConfig: r.config.RTC.CongestionControl, + PublishEnabledCodecs: enabledCodecs, + SubscribeEnabledCodecs: enabledCodecs, + Grants: pi.Grants, + Reconnect: pi.Reconnect, + Logger: pLogger, + Reporter: roomobs.NewNoopParticipantSessionReporter(), + ClientConf: clientConf, + ClientInfo: rtc.ClientInfo{ClientInfo: pi.Client}, + Region: pi.Region, + AdaptiveStream: pi.AdaptiveStream, + AllowTCPFallback: allowFallback, + TCPFallbackRTTThreshold: r.config.RTC.TCPFallbackRTTThreshold, + AllowUDPUnstableFallback: r.config.RTC.AllowUDPUnstableFallback, + TURNSEnabled: r.config.IsTURNSEnabled(), + ParticipantListener: room.LocalParticipantListener(), ParticipantHelper: &roomManagerParticipantHelper{ room: room, codecRegressionThreshold: r.config.Video.CodecRegressionThreshold,