chat.html: drop self-echo frames at onRxFrame entry
zebrad reads @DEFAULT_MONITOR@ which mixes every PA stream on a machine, so each browser tab hears its own carrier echoed back. without a filter, every outbound message would render twice in the chat log (once as 'me' at send time, once as 'peer' on echo arrival). filter: compare frame.sid (carried in DATA + HELLO) against our own senderIdBytes(). if equal, drop frame before any UI work. loopback mode unaffected since BroadcastChannel never echoes to sender by spec. senderIdBytes returns a stable per-tab id: * passphrase mode: random 4 bytes cached for tab lifetime * pubkey mode: first 4 of SHA-256(pubkey), stable across reloads
This commit is contained in:
parent
c8a755513f
commit
dcb1c8e5a1
1 changed files with 9 additions and 0 deletions
|
|
@ -772,6 +772,15 @@ async function onRxFrame(bytes) {
|
|||
logLine('err', `rx: malformed frame (type=${f.type}, ${f.error})`);
|
||||
return;
|
||||
}
|
||||
/* same-machine PA mix echoes our own carrier back to us. drop any frame
|
||||
* whose sender id matches our own so we don't double-render. loopback
|
||||
* mode is unaffected because BroadcastChannel never echoes to sender. */
|
||||
if (f.sid) {
|
||||
const mine = await senderIdBytes();
|
||||
let isSelf = true;
|
||||
for (let i = 0; i < 4; i++) if (f.sid[i] !== mine[i]) { isSelf = false; break; }
|
||||
if (isSelf) return;
|
||||
}
|
||||
if (f.type === T_OFFER) {
|
||||
logLine('sys', `rx: OFFER from peer — ${f.baud} baud`);
|
||||
/* respond with READY at handshake baud */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue