fix(e2ee): restore 3s key rotation wait, fix mute callback arg order

Removing the blocking wait entirely caused DEC_FAILED - the rotated key
had not arrived via nio sync before the pipeline started. Restore a short
3s wait (down from 10s) which is enough for nio to deliver the rotated key.

Also fix on_mute/on_unmute arg order (participant, publication - not reversed).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Christian Gick
2026-02-23 10:43:38 +02:00
parent a11cafc1d6
commit 277d6b5fe4

View File

@@ -408,11 +408,11 @@ class VoiceSession:
logger.info("Track pub: %s %s kind=%s", p.identity, pub.sid, pub.kind) logger.info("Track pub: %s %s kind=%s", p.identity, pub.sid, pub.kind)
@self.lk_room.on("track_muted") @self.lk_room.on("track_muted")
def on_mute(pub, p): def on_mute(p, pub):
logger.info("Track MUTED: %s %s kind=%s", p.identity, pub.sid, pub.kind) logger.info("Track MUTED: %s %s kind=%s", p.identity, pub.sid, pub.kind)
@self.lk_room.on("track_unmuted") @self.lk_room.on("track_unmuted")
def on_unmute(pub, p): def on_unmute(p, pub):
logger.info("Track UNMUTED: %s %s kind=%s", p.identity, pub.sid, pub.kind) logger.info("Track UNMUTED: %s %s kind=%s", p.identity, pub.sid, pub.kind)
@self.lk_room.on("track_subscribed") @self.lk_room.on("track_subscribed")
@@ -483,12 +483,24 @@ class VoiceSession:
ok = kp.set_key(bot_identity, self._bot_key, 0) ok = kp.set_key(bot_identity, self._bot_key, 0)
logger.info("Set bot key for %s (ok=%s, %d bytes)", bot_identity, ok, len(self._bot_key)) logger.info("Set bot key for %s (ok=%s, %d bytes)", bot_identity, ok, len(self._bot_key))
# Element Call may rotate keys when bot joins — handled asynchronously by # Element Call rotates its key when bot joins. Wait up to 3s for the
# on_encryption_key() (stores keys) + on_track_subscribed() / on_e2ee_state_changed() # rotated key to arrive via nio sync before proceeding. If it arrives,
# (applies keys when frame cryptor exists). No blocking wait needed. # on_encryption_key() stores it and (if track already subscribed) sets it.
logger.info("E2EE key state: %d keys stored (max_idx=%d)", pre_key_count = len(self._caller_all_keys)
len(self._caller_all_keys), pre_max_idx = max(self._caller_all_keys.keys()) if self._caller_all_keys else -1
max(self._caller_all_keys.keys()) if self._caller_all_keys else -1) logger.info("Waiting up to 3s for key rotation (current: %d keys, max_idx=%d)...",
pre_key_count, pre_max_idx)
for _wait in range(6): # 6 × 0.5s = 3s
await asyncio.sleep(0.5)
new_count = len(self._caller_all_keys)
new_max = max(self._caller_all_keys.keys()) if self._caller_all_keys else -1
if new_max > pre_max_idx or new_count > pre_key_count:
self._caller_key = self._caller_all_keys[new_max]
logger.info("Key rotated: index %d%d, count %d%d",
pre_max_idx, new_max, pre_key_count, new_count)
break
else:
logger.info("No key rotation after 3s — proceeding with key[%d]", pre_max_idx)
# Find the remote participant, wait up to 10s if not yet connected # Find the remote participant, wait up to 10s if not yet connected
remote_identity = None remote_identity = None