fix(vp8channel): client ignores frames from other participants

In single-peer mode (client), frames from unknown epochs are now
silently dropped instead of triggering a reconnect loop. This
prevents the client from mistaking another client's VP8 track
for a server restart.

Part of #67
This commit is contained in:
zarazaex69
2026-05-24 17:33:51 +03:00
parent cefd260e5d
commit d0b0b8e9db
2 changed files with 13 additions and 16 deletions

View File

@@ -680,19 +680,11 @@ func (p *streamTransport) handleIncomingFrame(frame []byte) {
if !p.hadPeer.Swap(true) {
p.handleFirstPeer(peerEpoch)
} else if prev := p.peerEpoch.Load(); prev != peerEpoch {
// Peer restarted its KCP session. Reset ours so the conv state
// machines re-converge. CAS guards against double-reset when
// fragmented frames straddle the epoch boundary.
if p.peerEpoch.CompareAndSwap(prev, peerEpoch) {
p.resetKCP()
p.reconnectMu.Lock()
fn := p.reconnectFn
p.reconnectMu.Unlock()
if fn != nil {
fn()
}
}
// Drop this packet: it predates our fresh KCP session.
// In a multi-participant room, other clients also publish VP8
// tracks. Their epochs differ from our latched peer (the server).
// Simply ignore frames that don't match our peer — they belong to
// other participants we don't communicate with.
logger.Debugf("vp8channel: ignoring frame from unknown epoch=0x%08x (latched=0x%08x)", peerEpoch, prev)
return
}

View File

@@ -374,8 +374,13 @@ func TestHandleIncomingFrameEpochFilteringAndReconnect(t *testing.T) {
t.Fatalf("stream reconnect did not reset/callback: reconnected=%v kcp=%v", reconnected, tr.kcp)
}
reconnected = false
tr.handleIncomingFrame(mkFrame(tr.bindingToken, 2, []byte("after-restart")))
if !reconnected || tr.peerEpoch.Load() != 2 || tr.kcp == nil {
t.Fatalf("epoch change did not reset/reconnect: reconnected=%v epoch=%d kcp=%v", reconnected, tr.peerEpoch.Load(), tr.kcp) //nolint:lll // long test description
// In single-peer mode, frames from a different epoch are ignored (other
// participants in the room). The client does NOT reconnect.
tr.handleIncomingFrame(mkFrame(tr.bindingToken, 2, []byte("other-participant")))
if reconnected {
t.Fatal("epoch change from another participant should not trigger reconnect")
}
if tr.peerEpoch.Load() != 1 {
t.Fatalf("peer epoch changed unexpectedly: got %d want 1", tr.peerEpoch.Load())
}
}