zebra-report: fetch ephemeral TURN credentials from /turn-cred

This commit is contained in:
russell@unturf.com 2026-05-28 13:27:33 -04:00
parent 11b6abaf13
commit 06c1e2bfec
No known key found for this signature in database

View file

@ -394,20 +394,32 @@ const PBKDF2_ITER = 600000;
const LOOPBACK = new URLSearchParams(location.search).has('loopback');
const RTC_CONFIG = {
iceServers: [
/* our STUN/TURN on proxy.uncloseai.com — coturn deployed via
* git.unturf.com/engineering/unturf/proxy.unturf.com.
* credentials are public by design (baked into a static page);
* rate-limited via coturn quotas, not via secrecy. */
{ urls: ['stun:proxy.uncloseai.com:3478', 'stun:stun.l.google.com:19302'] },
{
urls: 'turn:proxy.uncloseai.com:3478',
username: 'zebra',
credential: '7a4a2b1c8d9e6f5a'
}
]
/* STUN is free + needs no auth; TURN credentials are fetched fresh per
* connection from /turn-cred (time-limited HMAC, so each client gets its own
* coturn quota instead of sharing one static login). rtcConfig starts STUN-only
* and is upgraded with TURN once the creds arrive — if the fetch fails we still
* connect directly / via STUN, just without the relay fallback. */
const TURN_CRED_URL = new URLSearchParams(location.search).get('turncred')
|| 'https://cors-proxy.uncloseai.com/turn-cred';
let rtcConfig = {
iceServers: [{ urls: ['stun:proxy.uncloseai.com:3478', 'stun:stun.l.google.com:19302'] }]
};
async function refreshTurnCred() {
try {
const c = await (await fetch(TURN_CRED_URL, { cache: 'no-store' })).json();
if (c && c.credential && c.uris) {
rtcConfig = {
iceServers: [
{ urls: c.stun || ['stun:proxy.uncloseai.com:3478'] },
{ urls: c.uris, username: c.username, credential: c.credential }
]
};
logLine('sys', 'TURN credentials fetched (relay fallback available)');
}
} catch (e) {
logLine('sys', 'no TURN credentials — direct/STUN only (' + e.message + ')');
}
}
/* ============================================================== *
* tiny utils *
@ -1132,7 +1144,7 @@ const rtcStatus = $('rtc-status');
function ensurePC() {
if (pc) return pc;
if (!carrierOn) throw new Error('start carrier first');
pc = new RTCPeerConnection(RTC_CONFIG);
pc = new RTCPeerConnection(rtcConfig);
for (const tr of outboundStream.getTracks()) pc.addTrack(tr, outboundStream);
/* Force a memoryless codec (G.711 PCMU/PCMA, else G.722) ahead of Opus.
* Opus is a perceptual codec that re-quantizes in 20ms frames and smears the
@ -1338,6 +1350,7 @@ async function connectRelay() {
logLine('sys', 'carrier auto-started for relay connect');
} catch (e) { relaySet('carrier failed: ' + e.message, 'err'); return; }
}
await refreshTurnCred(); /* fetch fresh ephemeral TURN creds before the PC */
try {
relayKey = await deriveSignalKey(code);
const room = await deriveSignalRoom(code);