zebra-report: deploy silent-listener fix + listener-bye-on-bfcache fix
Pulls in two upstream zebra-report commits:
0ce1339 prefix-match in flushSfuStreams (kills the silent
fedora-chrome listener: ontrack races peer-joined, cache
keyed by 16-char streamID prefix, flush's strict-equality
matcher never resolved short→full, listener heard nothing
from anyone already in the room).
5e8cdad send 'bye' on pagehide for listeners even when
persisted=true (kills the closed-firefox-phone roster
zombies sitting through the 120s readTimeout window).
Server-side backstop (60s listenerAliveTTL) ships separately in
proxy.unturf.com main; the client fix above stands on its own for
the common bye-arrives case.
Fox 2026-06-06: "rebooting fedora chrome blanka because it never
could hear any speakers for days now".
This commit is contained in:
parent
0444bd1297
commit
3a0a30807e
5 changed files with 60 additions and 32 deletions
|
|
@ -507,9 +507,9 @@ handle /zebra-spaces-sfu* { reverse_proxy localhost:8092 { flush_interval -1
|
|||
</p>
|
||||
|
||||
<footer style="max-width:820px;margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
||||
<span style="color:#777">page integrity</span> · built <span class="stamp-date">2026-06-04</span><br>
|
||||
md5 <span class="stamp-md5">e4e8e782260db19486c05c042f4f1afc</span><br>
|
||||
sha256 <span class="stamp-sha">0d6678f32e1c4dcc0dd3adcb052b4b0cc5dc86fb6f2dbc5c9c79775e3feb683e</span><br>
|
||||
<span style="color:#777">page integrity</span> · built <span class="stamp-date">2026-06-06</span><br>
|
||||
md5 <span class="stamp-md5">f3900aa0c841baa7c61599ff247f8fe1</span><br>
|
||||
sha256 <span class="stamp-sha">496b0dee4967745d5502d549c30278370cbd228ae75c3020025f9912fa9773d7</span><br>
|
||||
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
|
||||
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify it against these hashes; point it at your own servers with ?signal= and ?turncred=</span>
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -341,9 +341,9 @@ try {
|
|||
</p>
|
||||
|
||||
<footer style="max-width:820px;margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
||||
<span style="color:#777">page integrity</span> · built <span class="stamp-date">2026-06-04</span><br>
|
||||
md5 <span class="stamp-md5">9870bd4e4dae3439f3238f6c7bfbb0e1</span><br>
|
||||
sha256 <span class="stamp-sha">7bf54074bc06b6a9378d75cfc678aadf626c2c2e921149db5610a7e0ed86ef6a</span><br>
|
||||
<span style="color:#777">page integrity</span> · built <span class="stamp-date">2026-06-06</span><br>
|
||||
md5 <span class="stamp-md5">ea02f55584d8042b03fcbd999e1da240</span><br>
|
||||
sha256 <span class="stamp-sha">c7cb5f8be8241d4634cca84acd3343c1fbfd0c7053b260bcee05084aa7bd83aa</span><br>
|
||||
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
|
||||
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify it against these hashes; point it at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -1747,9 +1747,9 @@ logLine('sys', 'chat content lives in encrypted SRTP audio. no IP packets carry
|
|||
})();
|
||||
</script>
|
||||
<footer style="max-width:820px;margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
||||
<span style="color:#777">page integrity</span> · built <span class="stamp-date">2026-06-04</span><br>
|
||||
md5 <span class="stamp-md5">b7b1b1b9c612636a17adf94eca5835b5</span><br>
|
||||
sha256 <span class="stamp-sha">7dff2ae15621b8c56d4c0c5a50afe5b3305317a161b281d66c2417c3b1cbf1a6</span><br>
|
||||
<span style="color:#777">page integrity</span> · built <span class="stamp-date">2026-06-06</span><br>
|
||||
md5 <span class="stamp-md5">e9fb81e6d445184e8a4967dfe56883f9</span><br>
|
||||
sha256 <span class="stamp-sha">a44a19223961e6a8e4f6010d073ff1e95246d908eb3b27d322fcd7bb17e5ad39</span><br>
|
||||
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
|
||||
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify it against these hashes; point it at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -747,9 +747,9 @@ else wirePuppet();
|
|||
</section>
|
||||
|
||||
<footer style="max-width:560px;margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
||||
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-04</span><br>
|
||||
md5 <span class="stamp-md5">704bc6f8c294b01704add1b59ec23d69</span><br>
|
||||
sha256 <span class="stamp-sha">06b739c56ebdfab90591ea4c5e8d8cb6b5cd854c02f526753f724857c518a64e</span><br>
|
||||
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-06</span><br>
|
||||
md5 <span class="stamp-md5">ba6a5714f597469b0aa61b32657f50f4</span><br>
|
||||
sha256 <span class="stamp-sha">78b5fb863ec406ec39081a0231fb909eef3abf332e84c0a5f25942f62f49de1b</span><br>
|
||||
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
|
||||
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify it against these hashes; point it at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
|
||||
</footer>
|
||||
|
|
|
|||
|
|
@ -3507,15 +3507,30 @@ function flushSfuStreams(){
|
|||
* fresh-attach on the same uuid and producing audible overlap.
|
||||
* Fox 2026-06-05 telemetry: "fxhp-android-firefox is hearing two
|
||||
* streams now as listener" — fix the wrong guard, not double-audio
|
||||
* via dedup. */
|
||||
* via dedup.
|
||||
*
|
||||
* Match by prefix: the cache key from handleRemoteSfuTrack is whatever
|
||||
* resolution returned at ontrack time — full pubhex if the member
|
||||
* roster already had the publisher, or the 16-char streamID prefix
|
||||
* otherwise (ontrack races peer-joined; SFU sub PC ontrack can fire
|
||||
* before signal-server announces existing speakers). Strict === on
|
||||
* the full-decoded mm pubkey would never match the prefix key, so a
|
||||
* listener that joined a room with N existing speakers stayed
|
||||
* permanently silent. Symmetry with the startsWith resolution in
|
||||
* handleRemoteSfuTrack (line ~4640). fox 2026-06-06: "fedora chrome
|
||||
* is flawless besides not able to hear any mics, was working a few
|
||||
* days back, only zebra code changed." */
|
||||
for (const [pubHex, stream] of sfuStreamsByPubHex){
|
||||
for (const [uuid, mm] of members){
|
||||
try {
|
||||
if (mm.pubkey && hex(unb64(mm.pubkey)) === pubHex){
|
||||
if (!remoteAudio.has(uuid) && !listenerAudioNodes.has(uuid)){
|
||||
attachSfuTrack(uuid, stream);
|
||||
if (mm.pubkey){
|
||||
const fh = hex(unb64(mm.pubkey));
|
||||
if (fh.startsWith(pubHex)){
|
||||
if (!remoteAudio.has(uuid) && !listenerAudioNodes.has(uuid)){
|
||||
attachSfuTrack(uuid, stream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch(_){}
|
||||
}
|
||||
|
|
@ -7556,20 +7571,33 @@ refreshSpeakerList();
|
|||
* this, a closed tab dies silently → hiccup grace → 8s of trailing
|
||||
* audio. Fox 2026-06-03.
|
||||
*
|
||||
* Critical guard: pagehide ALSO fires when the page goes into the
|
||||
* back-forward cache (mobile app-switch / lock screen / minimise),
|
||||
* with event.persisted=true. We must NOT send bye in that case —
|
||||
* the page is still alive, just paused; on pageshow it resumes with
|
||||
* the same WS / SFU / mesh state. Sending bye here would force the
|
||||
* server to evict the SFU PCs, and when the phone comes back the
|
||||
* resumed audio path stays muted (Fox 2026-06-03: "now the phone
|
||||
* leaving and coming back cannot hear the music").
|
||||
* Critical guard for SPEAKERS: pagehide ALSO fires when the page
|
||||
* goes into the back-forward cache (mobile app-switch / lock screen
|
||||
* / minimise), with event.persisted=true. A speaker on bfcache
|
||||
* MUST NOT send bye — finalizeLeave would post evictFromSFU on
|
||||
* their publisher AND subscriber PCs, and when the phone comes
|
||||
* back the resumed audio path stays muted (Fox 2026-06-03: "now
|
||||
* the phone leaving and coming back cannot hear the music").
|
||||
*
|
||||
* The JS heartbeat handles the bfcache case independently — while
|
||||
* the page is bfcached, setInterval is paused, so the server's
|
||||
* aliveTTL fires after 45s if the user doesn't come back. */
|
||||
* LISTENERS take the opposite branch: send bye even on persisted.
|
||||
* finalizeLeave already exempts listeners from evictFromSFU
|
||||
* (signal-server main.go line ~1089), so a listener bye is roster-
|
||||
* only — peer-left broadcast, member entry deleted, no eviction.
|
||||
* On pageshow the listener re-handshakes (sub PC + WS join) like
|
||||
* a cold join, same path that already works. The cost is a brief
|
||||
* "rejoin" appearance in other clients' rosters; the benefit is
|
||||
* the immediate disappearance of closed-Firefox-on-phone zombies
|
||||
* who otherwise wait out the 120s readTimeout + 8s hiccup grace
|
||||
* because listeners are exempt from the server's aliveJanitor.
|
||||
* Fox 2026-06-06: "closed firefox on both phones [they] are both
|
||||
* still in the list".
|
||||
*
|
||||
* The JS heartbeat handles the speaker bfcache case independently
|
||||
* — while the page is bfcached, setInterval is paused, so the
|
||||
* server's aliveTTL fires after 45s if the user doesn't come back. */
|
||||
function sendByeIfRealClose(ev){
|
||||
if (ev && ev.persisted) return; // bfcache — page is napping, not dying
|
||||
/* speaker on bfcache: keep the PCs warm, ride out the nap */
|
||||
if (ev && ev.persisted && myRole !== 'listener') return;
|
||||
try {
|
||||
if (ws && ws.readyState === WebSocket.OPEN){
|
||||
ws.send(JSON.stringify({ type: 'bye' }));
|
||||
|
|
@ -7875,9 +7903,9 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');
|
|||
</script>
|
||||
|
||||
<footer style="margin:2.2rem auto 0;font-size:0.65rem;color:#999;line-height:1.7;word-break:break-all;font-family:monospace">
|
||||
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-05</span><br>
|
||||
md5 <span class="stamp-md5">96bc1aa9b23545fe92f4dfe02dfda74c</span><br>
|
||||
sha256 <span class="stamp-sha">df6d1806da9b5844d6b9779ce84ae41fc21feeb4e2352a747a09662741bab08f</span><br>
|
||||
<span id="pi-seal" style="color:#777;cursor:default;user-select:none" title="">page integrity</span> · built <span class="stamp-date">2026-06-06</span><br>
|
||||
md5 <span class="stamp-md5">973996244966a40f7370e23bec5dcbb5</span><br>
|
||||
sha256 <span class="stamp-sha">66f3d4eebd028f7ea16ea58df624ed0d2223505ff5c99715730379757e613630</span><br>
|
||||
<span style="color:#bbb">hashes are of this page with these two fields zeroed — to verify, blank them and re-hash</span><br>
|
||||
<span style="color:#bbb">one self-contained file — <strong>save a copy</strong> and verify against these hashes; point at your own servers with ?signal= and ?turncred=, or <a href="host-your-own.html" style="color:#999">host your own community</a></span>
|
||||
</footer>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue