diff --git a/src/backend/core/api/__init__.py b/src/backend/core/api/__init__.py index 05ac309d..beb0ec3b 100644 --- a/src/backend/core/api/__init__.py +++ b/src/backend/core/api/__init__.py @@ -50,7 +50,10 @@ def get_frontend_configuration(request): else None, "default_country": settings.ROOM_TELEPHONY_DEFAULT_COUNTRY, }, - "livekit": {"url": settings.LIVEKIT_CONFIGURATION["url"]}, + "livekit": { + "url": settings.LIVEKIT_CONFIGURATION["url"], + "enable_firefox_proxy_workaround": settings.LIVEKIT_ENABLE_FIREFOX_PROXY_WORKAROUND, + }, } frontend_configuration.update(settings.FRONTEND_CONFIGURATION) return Response(frontend_configuration) diff --git a/src/backend/meet/settings.py b/src/backend/meet/settings.py index b423bcf0..f3ad1648 100755 --- a/src/backend/meet/settings.py +++ b/src/backend/meet/settings.py @@ -492,6 +492,11 @@ class Base(Configuration): ), "url": values.Value(environ_name="LIVEKIT_API_URL", environ_prefix=None), } + LIVEKIT_ENABLE_FIREFOX_PROXY_WORKAROUND = values.BooleanValue( + environ_name="LIVEKIT_ENABLE_FIREFOX_PROXY_WORKAROUND", + environ_prefix=None, + default=False, + ) LIVEKIT_VERIFY_SSL = values.BooleanValue( True, environ_name="LIVEKIT_VERIFY_SSL", environ_prefix=None ) diff --git a/src/frontend/src/api/useConfig.ts b/src/frontend/src/api/useConfig.ts index 876775da..887c6223 100644 --- a/src/frontend/src/api/useConfig.ts +++ b/src/frontend/src/api/useConfig.ts @@ -39,6 +39,7 @@ export interface ApiConfig { manifest_link?: string livekit: { url: string + enable_firefox_proxy_workaround: boolean } } diff --git a/src/frontend/src/features/rooms/components/Conference.tsx b/src/frontend/src/features/rooms/components/Conference.tsx index 27c0a303..891ce2e8 100644 --- a/src/frontend/src/features/rooms/components/Conference.tsx +++ b/src/frontend/src/features/rooms/components/Conference.tsx @@ -25,6 +25,7 @@ import { navigateTo } from '@/navigation/navigateTo' import { MediaDeviceErrorAlert } from './MediaDeviceErrorAlert' import { usePostHog } from 'posthog-js/react' import { useConfig } from '@/api/useConfig' +import { isFireFox } from '@/utils/livekit' export const Conference = ({ roomId, @@ -103,17 +104,40 @@ export const Conference = ({ * This prefetch helps reduce initial connection latency by establishing * an early HTTP connection to the WebRTC signaling server * - * FIREFOX + PROXY WORKAROUND: - * On Firefox behind proxy configurations, WebSocket signaling fails to establish. - * Client receives HTTP 200 instead of expected 101 (Switching Protocols). - * This appears to be a certificate/security issue where the initial request - * is considered unsecure. By first calling the signaling server via HTTPS, - * subsequent WebSocket establishment works correctly in these setups. - * This is a workaround - issue is reproducible on LiveKit's demo app. + * It should cache DNS and TLS keys. */ const prepareConnection = async () => { if (!apiConfig || isConnectionWarmedUp) return await room.prepareConnection(apiConfig.livekit.url) + + if (isFireFox() && apiConfig.livekit.enable_firefox_proxy_workaround) { + try { + const wssUrl = + apiConfig.livekit.url + .replace('https://', 'wss://') + .replace(/\/$/, '') + '/rtc' + + /** + * FIREFOX + PROXY WORKAROUND: + * + * Issue: On Firefox behind proxy configurations, WebSocket signaling fails to establish. + * Symptom: Client receives HTTP 200 instead of expected 101 (Switching Protocols). + * Root Cause: Certificate/security issue where the initial request is considered unsecure. + * + * Solution: Pre-establish a WebSocket connection to the signaling server, which fails. + * This "primes" the connection, allowing subsequent WebSocket establishments to work correctly. + * + * Note: This issue is reproducible on LiveKit's demo app. + * Reference: livekit-examples/meet/issues/466 + */ + const ws = new WebSocket(wssUrl) + // 401 unauthorized response is expected + ws.onerror = () => ws.readyState <= 1 && ws.close() + } catch (e) { + console.debug('Firefox WebSocket workaround failed.', e) + } + } + setIsConnectionWarmedUp(true) } prepareConnection() diff --git a/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl b/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl index 2b0ec523..c45d4de3 100644 --- a/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl +++ b/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl @@ -52,6 +52,7 @@ backend: {{- end }} {{- end }} LIVEKIT_API_URL: https://livekit.127.0.0.1.nip.io/ + LIVEKIT_ENABLE_FIREFOX_PROXY_WORKAROUND: True ALLOW_UNREGISTERED_ROOMS: False FRONTEND_SILENCE_LIVEKIT_DEBUG: False FRONTEND_SUPPORT: "{'id': '58ea6697-8eba-4492-bc59-ad6562585041', 'help_article_transcript': 'https://lasuite.crisp.help/fr/article/visio-transcript-1sjq43x', 'help_article_recording': 'https://lasuite.crisp.help/fr/article/visio-enregistrement-wgc8o0', 'help_article_more_tools': 'https://lasuite.crisp.help/fr/article/visio-tools-bvxj23'}"