@stream-io/video-client 1.57.0 → 1.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/e2ee-worker.browser.es.js +1342 -0
- package/dist/e2ee-worker.browser.es.js.map +1 -0
- package/dist/index.browser.es.js +831 -55
- package/dist/index.browser.es.js.map +1 -1
- package/dist/index.cjs.js +875 -54
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.es.js +864 -55
- package/dist/index.es.js.map +1 -1
- package/dist/src/Call.d.ts +52 -6
- package/dist/src/coordinator/connection/connection.d.ts +1 -1
- package/dist/src/devices/CameraManager.d.ts +6 -0
- package/dist/src/devices/DeviceManager.d.ts +1 -0
- package/dist/src/devices/MicrophoneManager.d.ts +6 -0
- package/dist/src/devices/SpeakerManager.d.ts +2 -1
- package/dist/src/events/participant.d.ts +10 -3
- package/dist/src/gen/coordinator/index.d.ts +1363 -243
- package/dist/src/gen/video/sfu/models/models.d.ts +8 -0
- package/dist/src/helpers/TypedEventEmitter.d.ts +23 -0
- package/dist/src/helpers/ensureExhausted.d.ts +1 -1
- package/dist/src/permissions/PermissionsContext.d.ts +2 -2
- package/dist/src/rtc/BasePeerConnection.d.ts +3 -1
- package/dist/src/rtc/e2ee/E2EEManager.d.ts +12 -0
- package/dist/src/rtc/e2ee/EncryptionManager.d.ts +148 -0
- package/dist/src/rtc/e2ee/e2ee-worker.d.ts +25 -0
- package/dist/src/rtc/e2ee/events.d.ts +163 -0
- package/dist/src/rtc/e2ee/transformSupport.d.ts +21 -0
- package/dist/src/rtc/helpers/rtcConfiguration.d.ts +2 -2
- package/dist/src/rtc/index.d.ts +1 -0
- package/dist/src/rtc/mediaEngine.d.ts +23 -0
- package/dist/src/rtc/types.d.ts +2 -0
- package/dist/src/store/CallState.d.ts +21 -0
- package/dist/src/types.d.ts +15 -6
- package/index.ts +3 -0
- package/package.json +1 -1
- package/src/Call.ts +160 -26
- package/src/__tests__/Call.test.ts +15 -0
- package/src/coordinator/connection/connection.ts +6 -3
- package/src/devices/AudioDeviceManager.ts +6 -0
- package/src/devices/CameraManager.ts +51 -4
- package/src/devices/DeviceManager.ts +17 -0
- package/src/devices/MicrophoneManager.ts +55 -5
- package/src/devices/ScreenShareManager.ts +3 -0
- package/src/devices/SpeakerManager.ts +42 -12
- package/src/devices/__tests__/MicrophoneManagerRN.test.ts +1 -20
- package/src/devices/__tests__/SpeakerManager.test.ts +138 -42
- package/src/devices/__tests__/mocks.ts +36 -3
- package/src/events/__tests__/participant.test.ts +134 -1
- package/src/events/callEventHandlers.ts +9 -3
- package/src/events/participant.ts +42 -7
- package/src/gen/coordinator/index.ts +1384 -244
- package/src/gen/video/sfu/models/models.ts +15 -0
- package/src/helpers/TypedEventEmitter.ts +71 -0
- package/src/helpers/__tests__/TypedEventEmitter.test.ts +133 -0
- package/src/helpers/ensureExhausted.ts +4 -2
- package/src/permissions/PermissionsContext.ts +10 -5
- package/src/rtc/BasePeerConnection.ts +12 -1
- package/src/rtc/Publisher.ts +8 -0
- package/src/rtc/Subscriber.ts +5 -0
- package/src/rtc/__tests__/Publisher.test.ts +101 -0
- package/src/rtc/__tests__/Subscriber.test.ts +89 -0
- package/src/rtc/__tests__/mocks/webrtc.mocks.ts +31 -0
- package/src/rtc/e2ee/E2EEManager.ts +12 -0
- package/src/rtc/e2ee/EncryptionManager.ts +336 -0
- package/src/rtc/e2ee/SPEC.md +586 -0
- package/src/rtc/e2ee/__tests__/E2EEManager.contract.test.ts +39 -0
- package/src/rtc/e2ee/__tests__/EncryptionManager.test.ts +490 -0
- package/src/rtc/e2ee/__tests__/codec.test.ts +247 -0
- package/src/rtc/e2ee/__tests__/conformance.test.ts +184 -0
- package/src/rtc/e2ee/__tests__/failureTracker.test.ts +45 -0
- package/src/rtc/e2ee/__tests__/frameCounter.test.ts +90 -0
- package/src/rtc/e2ee/__tests__/keyStore.test.ts +221 -0
- package/src/rtc/e2ee/__tests__/notifications.test.ts +166 -0
- package/src/rtc/e2ee/__tests__/perf.test.ts +139 -0
- package/src/rtc/e2ee/__tests__/queue.test.ts +61 -0
- package/src/rtc/e2ee/__tests__/replayWindow.test.ts +133 -0
- package/src/rtc/e2ee/__tests__/trailer.test.ts +143 -0
- package/src/rtc/e2ee/__tests__/transform-pipeline.test.ts +839 -0
- package/src/rtc/e2ee/__tests__/transformSupport.test.ts +65 -0
- package/src/rtc/e2ee/e2ee-worker/codec.ts +220 -0
- package/src/rtc/e2ee/e2ee-worker/constants.ts +47 -0
- package/src/rtc/e2ee/e2ee-worker/decode.ts +159 -0
- package/src/rtc/e2ee/e2ee-worker/e2ee-worker-impl.ts +137 -0
- package/src/rtc/e2ee/e2ee-worker/encode.ts +147 -0
- package/src/rtc/e2ee/e2ee-worker/failureTracker.ts +26 -0
- package/src/rtc/e2ee/e2ee-worker/frameCounter.ts +37 -0
- package/src/rtc/e2ee/e2ee-worker/keyStore.ts +211 -0
- package/src/rtc/e2ee/e2ee-worker/notifications.ts +190 -0
- package/src/rtc/e2ee/e2ee-worker/perf.ts +129 -0
- package/src/rtc/e2ee/e2ee-worker/queue.ts +12 -0
- package/src/rtc/e2ee/e2ee-worker/replayWindow.ts +131 -0
- package/src/rtc/e2ee/e2ee-worker/trailer.ts +155 -0
- package/src/rtc/e2ee/e2ee-worker/tsconfig.json +8 -0
- package/src/rtc/e2ee/e2ee-worker/types.ts +29 -0
- package/src/rtc/e2ee/e2ee-worker.ts +27 -0
- package/src/rtc/e2ee/events.ts +179 -0
- package/src/rtc/e2ee/transformSupport.ts +35 -0
- package/src/rtc/helpers/rtcConfiguration.ts +4 -2
- package/src/rtc/index.ts +1 -0
- package/src/rtc/mediaEngine.ts +44 -0
- package/src/rtc/types.ts +2 -0
- package/src/store/CallState.ts +33 -1
- package/src/store/__tests__/CallState.test.ts +82 -1
- package/src/types.ts +23 -5
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2ee-worker.browser.es.js","sources":["../src/rtc/e2ee/e2ee-worker.ts"],"sourcesContent":["export function e2eeWorker() {\n /**\n * Codec-specific framing: how many header bytes stay clear, and H.264 RBSP\n * escaping so ciphertext cannot contain a fake Annex B start code.\n */\n const findStartCode = (data, offset) => {\n for (let i = offset; i < data.length - 2; ++i) {\n if (data[i] === 0 && data[i + 1] === 0) {\n if (data[i + 2] === 1) return { pos: i, len: 3 };\n if (data[i + 2] === 0 && i + 3 < data.length && data[i + 3] === 1) {\n return { pos: i, len: 4 };\n }\n }\n }\n return null;\n };\n /**\n * Clear bytes up to the first slice NALU (type 1 or 5) plus 2: start code,\n * NALU header, one byte of slice header. Ignores frameType, to match\n * {@link CodecProfile.clearBytes}.\n */\n const h264ClearBytes = (_frameType, data) => {\n let sc = findStartCode(data, 0);\n while (sc) {\n const headerPos = sc.pos + sc.len;\n if (headerPos >= data.length) break;\n const naluType = data[headerPos] & 0x1f;\n if (naluType === 1 || naluType === 5) {\n const clear = sc.pos + sc.len + 2;\n // A real slice header exceeds 2 bytes, so this clamp should never bite.\n return clear > data.length ? data.length : clear;\n }\n sc = findStartCode(data, headerPos);\n }\n return 0;\n };\n /**\n * Escape-state seed for the clear-header boundary: how many 0x00 bytes end the\n * clear header, capped at 2 (a longer run does not change the escaper's next\n * decision).\n *\n * The clear header itself is never escaped, but its tail and the first escaped\n * bytes form one contiguous stream on the wire: a header ending in 0x00\n * followed by ciphertext starting 0x00 0x01 is a fake start code the\n * packetizer would split on. Seeding the escaper as if the header's zeros were\n * already scanned closes that gap. Encode and decode both derive the seed from\n * the same clear bytes, so nothing extra travels in the frame.\n */\n const boundarySeedZeros = (clearHeader) => {\n const n = clearHeader.length;\n let zeros = 0;\n while (zeros < 2 && zeros < n && clearHeader[n - 1 - zeros] === 0) zeros++;\n return zeros;\n };\n /**\n * Escaped length of `segments`, read as one contiguous stream so a 0x00 0x00\n * run spanning a boundary counts. Sizes the buffer for {@link rbspEscapeInto}.\n *\n * @param seedZeros zero-run state entering the stream; see\n * {@link boundarySeedZeros}.\n */\n const rbspEscapedLength = (segments, seedZeros) => {\n let total = 0;\n let zeros = seedZeros;\n for (const seg of segments) {\n total += seg.length;\n for (let i = 0; i < seg.length; ++i) {\n const byte = seg[i];\n if (zeros >= 2 && byte <= 3) {\n total++;\n zeros = 0;\n }\n zeros = byte === 0 ? zeros + 1 : 0;\n }\n }\n return total;\n };\n /**\n * Escape `segments` into `dst` at `offset`, inserting 0x03 after each 0x00 0x00\n * run followed by 0x00-0x03. `dst` needs {@link rbspEscapedLength} bytes free,\n * computed with the same `seedZeros`.\n *\n * Sizing separately lets the encoder escape straight behind the clear header,\n * copying the ciphertext once instead of twice.\n */\n const rbspEscapeInto = (dst, offset, segments, seedZeros) => {\n let j = offset;\n let zeros = seedZeros;\n for (const seg of segments) {\n for (let i = 0; i < seg.length; ++i) {\n const byte = seg[i];\n if (zeros >= 2 && byte <= 3) {\n dst[j++] = 3;\n zeros = 0;\n }\n dst[j++] = byte;\n zeros = byte === 0 ? zeros + 1 : 0;\n }\n }\n };\n /**\n * Reverse of {@link rbspEscapeInto}: drop each 0x03 the escaper inserted,\n * tracked with the same zero-run state so an escape byte right at the\n * clear-header boundary (possible only with a non-zero `seedZeros`) is\n * recognized too.\n */\n const rbspUnescape = (data, seedZeros) => {\n const isEscapeByte = (i, zeros) =>\n zeros >= 2 && data[i] === 3 && i + 1 < data.length && data[i + 1] <= 3;\n let remove = 0;\n let zeros = seedZeros;\n for (let i = 0; i < data.length; ++i) {\n if (isEscapeByte(i, zeros)) {\n remove++;\n zeros = 0;\n continue;\n }\n zeros = data[i] === 0 ? zeros + 1 : 0;\n }\n if (remove === 0) return data;\n const result = new Uint8Array(data.length - remove);\n let j = 0;\n zeros = seedZeros;\n for (let i = 0; i < data.length; ++i) {\n if (isEscapeByte(i, zeros)) {\n zeros = 0;\n continue;\n }\n result[j++] = data[i];\n zeros = data[i] === 0 ? zeros + 1 : 0;\n }\n return result;\n };\n // Audio has no keyframes, so the absence of a frame type identifies it. Keep\n // the Opus TOC byte clear. Only reached for audio: `audioOnly` rejects a video\n // frame before this runs.\n const defaultClearBytes = (frameType) => (frameType === undefined ? 1 : 0);\n // Clamped to the frame length. A short frame claiming more would make encode\n // zero-pad the header and decode build an AAD of a different length.\n const vpClearBytes = (frameType, data) => {\n const clear = frameType === 'key' ? 10 : 3;\n return clear > data.length ? data.length : clear;\n };\n // AV1 is absent on purpose: the AV1 RTP packetizer parses the OBU stream, so a\n // frame trailer does not survive. It needs its own scheme. Without an entry it\n // falls through to isSupportedCodec and fails closed.\n const CODEC_PROFILES = {\n opus: { rbsp: false, audioOnly: true, clearBytes: defaultClearBytes },\n vp8: { rbsp: false, audioOnly: false, clearBytes: vpClearBytes },\n vp9: { rbsp: false, audioOnly: false, clearBytes: vpClearBytes },\n h264: { rbsp: true, audioOnly: false, clearBytes: h264ClearBytes },\n };\n // Used when the caller names no codec. Audio is safe to frame unlabeled, since\n // the TOC byte rule holds for any audio codec. Video is not: the right clear\n // header and whether to escape both depend on the codec, so it fails closed.\n const DEFAULT_PROFILE = {\n rbsp: false,\n audioOnly: true,\n clearBytes: defaultClearBytes,\n };\n // Object.hasOwn, not `in`: `in` walks the prototype chain, so a codec named\n // like an Object.prototype member ('toString') would resolve to a function\n // instead of a profile.\n const getCodecProfile = (codec) =>\n codec !== undefined && Object.hasOwn(CODEC_PROFILES, codec)\n ? CODEC_PROFILES[codec]\n : DEFAULT_PROFILE;\n const isSupportedCodec = (codec) =>\n codec === undefined || Object.hasOwn(CODEC_PROFILES, codec);\n\n let tail = Promise.resolve();\n /**\n * Run tasks FIFO, one at a time, so a `setKey` cannot race transform setup.\n * `tail` swallows errors so one rejection cannot stall the queue; the returned\n * promise still carries that task's own outcome.\n */\n const enqueue = (fn) => {\n const run = tail.then(fn);\n tail = run.catch(() => {});\n return run;\n };\n\n /** Marks an encrypted frame's trailer. */\n const MAGIC = 0xe2eefeed;\n /**\n * Wire format version. Bump it when the trailer layout or IV derivation change.\n *\n * v1: [4B frameCounter][8B ivPrefix][1B keyIndex][2B clearBytes|flags]\n * [1B version][4B magic]. IV = ivPrefix ∥ frameCounter.\n */\n const E2EE_VERSION = 1;\n const IV_PREFIX_LEN = 8;\n const FRAME_COUNTER_LEN = 4;\n const IV_LEN = IV_PREFIX_LEN + FRAME_COUNTER_LEN;\n const KEY_INDEX_LEN = 1;\n const CLEAR_BYTES_LEN = 2;\n const VERSION_LEN = 1;\n const MAGIC_LEN = 4;\n /** 4 + 8 + 1 + 2 + 1 + 4 */\n const TRAILER_LEN =\n FRAME_COUNTER_LEN +\n IV_PREFIX_LEN +\n KEY_INDEX_LEN +\n CLEAR_BYTES_LEN +\n VERSION_LEN +\n MAGIC_LEN;\n /** Bit 15 of the clearBytes field. Signals RBSP escaping. */\n const RBSP_FLAG = 0x8000;\n /** Bit 15 belongs to RBSP_FLAG, so clearBytes gets 15 bits. */\n const MAX_CLEAR_BYTES = 0x7fff;\n const EMPTY_AAD = new Uint8Array(0);\n /** Consecutive decrypt failures on one track before `e2ee.decryption_stalled` fires. */\n const FAILURE_TOLERANCE = 10;\n /** Replay window in frames. A counter <= highestSeen - this is rejected. */\n const REPLAY_WINDOW = 1024;\n /**\n * One more than this wraps into an (ivPrefix, counter) pair the sender already\n * used, which is IV reuse under AES-GCM. Encoding throws instead.\n */\n const COUNTER_HARD_LIMIT = 0xffffffff; // 2^32 - 1\n\n /** At most one notification per second per key. */\n const THROTTLE_INTERVAL_MS = 1000;\n /**\n * Rate limiter keyed by an arbitrary string, so one throttle can cover several\n * independent conditions (a keyIndex, a userId) without them muting each other.\n *\n * Lives here because throttling is a delivery rule, not a general utility -\n * every user of it is in this file.\n */\n class Throttle {\n intervalMs;\n lastFiredAt = new Map();\n constructor(intervalMs) {\n this.intervalMs = intervalMs;\n }\n /**\n * True at most once per `intervalMs` for that key, so a sustained failure\n * cannot flood the host with notifications.\n */\n tryFire = (key) => {\n const now = Date.now();\n if (now - (this.lastFiredAt.get(key) ?? 0) > this.intervalMs) {\n this.lastFiredAt.set(key, now);\n return true;\n }\n return false;\n };\n }\n /**\n * Internal log-only channel: no `E2EEEventMap` entry, so the manager logs it\n * rather than emitting it to the host.\n */\n const reportError = (message) => {\n self.postMessage({ type: 'e2ee.error', message });\n };\n /**\n * The encoder holds no key, so every outgoing frame is dropped. Without this\n * the host just sees black video with nothing to act on. Throttled per user,\n * and stops on its own once a key arrives.\n *\n * Module-scoped rather than per transform: this condition is per user by\n * definition, so every track sharing one throttle is the point.\n */\n const missingKeyThrottle = new Throttle(THROTTLE_INTERVAL_MS);\n const notifyMissingEncodeKey = (userId) => {\n if (missingKeyThrottle.tryFire(userId)) {\n self.postMessage({ type: 'e2ee.missing_key', userId });\n }\n };\n /** Encode-side signals for one track. */\n class EncodeNotifier {\n userId;\n trackType;\n /** True once a failure was reported, until {@link recovered} re-arms it. */\n latched = false;\n constructor(userId, trackType) {\n this.userId = userId;\n this.trackType = trackType;\n }\n /** First failure of a run; silent until {@link recovered} re-arms it. */\n failed = (reason) => {\n if (this.latched) return;\n this.latched = true;\n self.postMessage({\n type: 'e2ee.encryption_failed',\n userId: this.userId,\n trackType: this.trackType,\n reason,\n });\n };\n /**\n * A frame encrypted again, so the next failure is worth reporting. Re-arming\n * is deliberate: it stops one early transient error from hiding a later\n * permanent one, such as the frame-counter hard limit.\n */\n recovered = () => {\n this.latched = false;\n };\n }\n /**\n * Decode-side signals for one track.\n *\n * One notifier is one track, so `userId` is constant: each throttle holds a\n * single entry and limits that track alone.\n */\n class DecodeNotifier {\n userId;\n trackType;\n failureThrottle = new Throttle(THROTTLE_INTERVAL_MS);\n /**\n * A key in flight, or a rotation whose keyIndex has not arrived, are both\n * normal. Keyed by keyIndex: one signal per key epoch.\n */\n missingKeyThrottle = new Throttle(THROTTLE_INTERVAL_MS);\n cleartextThrottle = new Throttle(THROTTLE_INTERVAL_MS);\n /**\n * Keyed by user, deliberately not by version. A sender's version is a\n * compile-time constant, so a track only ever sees one value legitimately -\n * while the byte is plaintext, so a relay rewriting it per frame would\n * otherwise get one event per distinct value and multiply the rate by 255.\n */\n versionThrottle = new Throttle(THROTTLE_INTERVAL_MS);\n /**\n * True once a `decryption_failed` reached the host. Pairs the two signals:\n * only a delivered failure needs clearing, and clearing it re-arms this.\n */\n failureReported = false;\n constructor(userId, trackType) {\n this.userId = userId;\n this.trackType = trackType;\n }\n /** GCM tag failure. Throttled; records that a failure reached the host. */\n failed = () => {\n if (!this.failureThrottle.tryFire(this.userId)) return;\n this.failureReported = true;\n self.postMessage({\n type: 'e2ee.decryption_failed',\n userId: this.userId,\n trackType: this.trackType,\n });\n };\n /** Paired with {@link failed}: no-op unless a failure was delivered. */\n resumed = () => {\n if (!this.failureReported) return;\n this.failureReported = false;\n self.postMessage({\n type: 'e2ee.decryption_resumed',\n userId: this.userId,\n trackType: this.trackType,\n });\n };\n /** A frame named a key this peer does not hold. Throttled per keyIndex. */\n missingKey = (keyIndex) => {\n if (!this.missingKeyThrottle.tryFire(String(keyIndex))) return;\n self.postMessage({\n type: 'e2ee.missing_key',\n userId: this.userId,\n trackType: this.trackType,\n keyIndex,\n });\n };\n /**\n * A frame carried this format but a version this build cannot decrypt, so it\n * was dropped. Throttled per track.\n */\n unsupportedVersion = (version) => {\n if (!this.versionThrottle.tryFire(this.userId)) return;\n self.postMessage({\n type: 'e2ee.unsupported_version',\n userId: this.userId,\n trackType: this.trackType,\n version,\n });\n };\n /** A frame carried no E2EE framing and was forwarded as-is. Throttled. */\n unencrypted = () => {\n if (!this.cleartextThrottle.tryFire(this.userId)) return;\n self.postMessage({\n type: 'e2ee.unencrypted_frame',\n userId: this.userId,\n trackType: this.trackType,\n });\n };\n /** Consecutive failures crossed the tolerance. Already once-per-run. */\n stalled = (keyIndex) => {\n self.postMessage({\n type: 'e2ee.decryption_stalled',\n userId: this.userId,\n trackType: this.trackType,\n keyIndex,\n });\n };\n }\n\n const getOrCreate = (map, userId) => {\n let inner = map.get(userId);\n if (!inner) {\n inner = new Map();\n map.set(userId, inner);\n }\n return inner;\n };\n const randomBytes = (n) => {\n const bytes = new Uint8Array(n);\n crypto.getRandomValues(bytes);\n return bytes;\n };\n const fingerprint = async (rawKey) => {\n const hash = await crypto.subtle.digest('SHA-256', rawKey);\n return new Uint8Array(hash, 0, 8);\n };\n /**\n * The buffer length picks the variant; EncryptionManager already validated it\n * as 16 or 32 bytes. Passing `length` keeps WebCrypto unambiguous across\n * browsers.\n */\n const aesGcmParams = (rawKey) => ({\n name: 'AES-GCM',\n length: rawKey.byteLength * 8,\n });\n /**\n * Import into a non-extractable CryptoKey, with a fresh random IV prefix and\n * the fingerprint. The fresh prefix is what lets the same raw key be imported\n * again without IV reuse.\n */\n const importKeyMaterial = async (rawKey) => {\n const [key, fp] = await Promise.all([\n crypto.subtle.importKey('raw', rawKey, aesGcmParams(rawKey), false, [\n 'encrypt',\n 'decrypt',\n ]),\n fingerprint(rawKey),\n ]);\n return { key, ivPrefix: randomBytes(IV_PREFIX_LEN), fingerprint: fp };\n };\n const toHex = (bytes) =>\n Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('');\n class KeyStore {\n perUserKeys = new Map();\n latestKeyIndex = new Map();\n /** Shared receive keys retained by epoch so in-flight frames survive rotation. */\n sharedKeys = new Map();\n /** The shared epoch used for encode fallback. Older retained epochs never win. */\n activeSharedKeyIndex;\n /**\n * Decryption key for (userId, keyIndex): per-user entry, else the shared key\n * at that index. The keyIndex comes from the frame trailer.\n */\n getKey = (userId, keyIndex) => {\n const perUser = this.perUserKeys.get(userId)?.get(keyIndex);\n if (perUser) return perUser.key;\n return this.sharedKeys.get(keyIndex)?.key;\n };\n /**\n * The encode path's only lookup: latest per-user key, else the explicitly\n * active shared key. Retained shared epochs are receive-only. The `ivPrefix`\n * rides along so the encoder never resolves the same material twice.\n */\n getLatestKey = (userId) => {\n const idx = this.latestKeyIndex.get(userId);\n if (idx !== undefined) {\n const km = this.perUserKeys.get(userId)?.get(idx);\n if (km) return { key: km.key, keyIndex: idx, ivPrefix: km.ivPrefix };\n }\n if (this.activeSharedKeyIndex === undefined) return null;\n const shared = this.sharedKeys.get(this.activeSharedKeyIndex);\n return shared\n ? {\n key: shared.key,\n keyIndex: this.activeSharedKeyIndex,\n ivPrefix: shared.ivPrefix,\n }\n : null;\n };\n importKey = async (userId, keyIndex, rawKey) => {\n try {\n getOrCreate(this.perUserKeys, userId).set(\n keyIndex,\n await importKeyMaterial(rawKey),\n );\n this.latestKeyIndex.set(userId, keyIndex);\n } catch (e) {\n reportError(\n `Failed to import key for user ${userId}: ${e?.message || e}`,\n );\n }\n };\n importSharedKey = async (keyIndex, rawKey) => {\n try {\n const material = await importKeyMaterial(rawKey);\n this.sharedKeys.set(keyIndex, material);\n this.activeSharedKeyIndex = keyIndex;\n } catch (e) {\n reportError(`Failed to import shared key: ${e?.message || e}`);\n }\n };\n /**\n * Retire exactly one of a user's epochs, leaving the rest usable.\n *\n * Clearing `latestKeyIndex` along with the slot is load-bearing. Left on a\n * removed index, {@link getLatestKey} resolves nothing there and falls\n * through to the active shared epoch, so the local user's frames would\n * quietly move from a key only they hold to one every participant holds. No\n * older epoch is promoted either, matching {@link removeSharedKey}.\n */\n removeKey = (userId, keyIndex) => {\n const perKeyIndex = this.perUserKeys.get(userId);\n if (!perKeyIndex?.delete(keyIndex)) return;\n if (perKeyIndex.size === 0) this.perUserKeys.delete(userId);\n if (this.latestKeyIndex.get(userId) === keyIndex) {\n this.latestKeyIndex.delete(userId);\n }\n };\n /**\n * Leaves the frame counters intact on purpose: a reset counter would reuse\n * IVs if the same raw key is imported again later. They live in\n * `frameCounter.ts`, so this cannot reach them even by accident.\n */\n removeAllKeys = (userId) => {\n this.perUserKeys.delete(userId);\n this.latestKeyIndex.delete(userId);\n };\n /**\n * Removes exactly one shared receive epoch. Removing the active epoch also\n * disables shared-key encode fallback; an older epoch is never reactivated\n * implicitly because doing so could resume sending with a retired key.\n */\n removeSharedKey = (keyIndex) => {\n this.sharedKeys.delete(keyIndex);\n if (this.activeSharedKeyIndex === keyIndex) {\n this.activeSharedKeyIndex = undefined;\n }\n };\n /**\n * Debug snapshot. Fingerprints only: enough to confirm a sender and receiver\n * hold matching key material, and it exposes no key.\n */\n keyState = () => ({\n perUserKeys: Array.from(this.perUserKeys).flatMap(\n ([userId, perKeyIndex]) =>\n Array.from(perKeyIndex, ([keyIndex, km]) => ({\n userId,\n keyIndex,\n fingerprint: toHex(km.fingerprint),\n })),\n ),\n sharedKeys: Array.from(this.sharedKeys, ([keyIndex, material]) => ({\n keyIndex,\n fingerprint: toHex(material.fingerprint),\n isActive: keyIndex === this.activeSharedKeyIndex,\n })),\n });\n /**\n * @internal Test-only. Production teardown is `Worker.terminate()`, which\n * reclaims the whole worker.\n */\n clear = () => {\n this.perUserKeys.clear();\n this.latestKeyIndex.clear();\n this.sharedKeys.clear();\n this.activeSharedKeyIndex = undefined;\n };\n }\n /** The worker has exactly one. */\n const keyStore = new KeyStore();\n\n /**\n * Whether reporting is on. Module-scoped rather than per registry: the worker\n * has exactly one of each, and a single flag keeps encode and decode from\n * drifting apart.\n */\n let perfEnabled = false;\n let perfInterval = null;\n let perfLastTick = 0;\n /**\n * Counter handle for one track, held by that track's transform for its\n * lifetime. Every method no-ops while reporting is off.\n */\n class TrackStats {\n stats;\n key;\n labels;\n constructor(stats, key, labels) {\n this.stats = stats;\n this.key = key;\n this.labels = labels;\n }\n /**\n * This track's accumulator, created on first use. Lazy on purpose: the entry\n * is what puts a row in the next report, so a track that goes idle after a\n * flush drops out instead of reporting 0 fps forever.\n */\n entry = () => {\n if (!perfEnabled) return undefined;\n let stat = this.stats.get(this.key);\n if (!stat) {\n stat = { ...this.labels, count: 0, maxCryptoMs: 0 };\n this.stats.set(this.key, stat);\n }\n return stat;\n };\n /** Count one frame through the transform. */\n bump = () => {\n const stat = this.entry();\n if (stat) stat.count++;\n };\n /** Timestamp to hand back to {@link endCrypto}; 0 while disabled. */\n startCrypto = () => (perfEnabled ? performance.now() : 0);\n endCrypto = (startedAt) => {\n const stat = this.entry();\n if (!stat) return;\n stat.maxCryptoMs = Math.max(\n stat.maxCryptoMs,\n performance.now() - startedAt,\n );\n };\n }\n /**\n * Per-track counters for one direction. The key is unique per track, so a vp8\n * camera and a vp8 screen share (encode), or a peer's audio and video (decode),\n * are reported apart instead of summed.\n */\n class StatsRegistry {\n stats = new Map();\n track = (key, labels) => new TrackStats(this.stats, key, labels);\n /** Drain all accumulators into per-track rates. */\n flush = (dtSec) => {\n const samples = Array.from(\n this.stats.values(),\n ({ count, maxCryptoMs, ...labels }) => ({\n ...labels,\n fps: count / dtSec,\n maxCryptoMs,\n }),\n );\n this.stats.clear();\n return samples;\n };\n clear = () => this.stats.clear();\n removeUser = (userId) => {\n for (const [key, stat] of this.stats) {\n if (stat.userId === userId) this.stats.delete(key);\n }\n };\n }\n const encodeStats = new StatsRegistry();\n const decodeStats = new StatsRegistry();\n const startPerfReport = () => {\n if (perfInterval) return; // a second interval would leak\n perfEnabled = true;\n perfLastTick = performance.now();\n perfInterval = setInterval(() => {\n const now = performance.now();\n const dtSec = Math.max(0.001, (now - perfLastTick) / 1000);\n perfLastTick = now;\n self.postMessage({\n type: 'e2ee.perf_report',\n encode: encodeStats.flush(dtSec),\n decode: decodeStats.flush(dtSec),\n });\n }, 1000);\n };\n const stopPerfReport = () => {\n perfEnabled = false;\n if (perfInterval) {\n clearInterval(perfInterval);\n perfInterval = null;\n }\n encodeStats.clear();\n decodeStats.clear();\n };\n\n /**\n * The on-wire framing: the 20-byte trailer appended to every encrypted frame,\n * and the 12-byte IV both directions derive.\n *\n * Write and read live together on purpose. They are one contract - the encoder\n * lays out bytes the decoder must find at the same offsets - so the layout is\n * defined once, here, and a change to it is a wire break: bump\n * {@link E2EE_VERSION} and regenerate the SPEC section 11 vectors.\n *\n * Layout, from the trailer's first byte:\n * [4B frameCounter][8B ivPrefix][1B keyIndex][2B clearBytes|flags]\n * [1B version][4B magic]\n */\n const OFF_IV_PREFIX = FRAME_COUNTER_LEN; // 4\n const OFF_KEY_INDEX = OFF_IV_PREFIX + IV_PREFIX_LEN; // 12\n const OFF_CLEAR_BYTES = OFF_KEY_INDEX + 1; // 13\n const OFF_VERSION = OFF_CLEAR_BYTES + 2; // 15\n const OFF_MAGIC = OFF_VERSION + 1; // 16\n /**\n * Fill a pre-allocated 12-byte IV: `[8B ivPrefix][4B frameCounter, BE]`.\n *\n * The encoder builds it from its own prefix and counter; the decoder rebuilds\n * the identical bytes from the trailer. The buffer is reused across frames\n * rather than allocated per frame - this runs once per frame on every track.\n */\n const fillIV = (iv, ivView, prefix, frameCounter) => {\n iv.set(prefix, 0);\n ivView.setUint32(IV_PREFIX_LEN, frameCounter);\n };\n const writeTrailer = (\n dst,\n offset,\n frameCounter,\n ivPrefix,\n keyIndex,\n clearBytes,\n isRbsp,\n ) => {\n if (clearBytes > MAX_CLEAR_BYTES) {\n throw new Error(\n `clearBytes ${clearBytes} exceeds 15-bit max ${MAX_CLEAR_BYTES}`,\n );\n }\n if (ivPrefix.length !== IV_PREFIX_LEN) {\n throw new Error(\n `ivPrefix must be ${IV_PREFIX_LEN} bytes, got ${ivPrefix.length}`,\n );\n }\n const view = new DataView(dst.buffer, dst.byteOffset, dst.byteLength);\n view.setUint32(offset, frameCounter);\n dst.set(ivPrefix, offset + OFF_IV_PREFIX);\n dst[offset + OFF_KEY_INDEX] = keyIndex;\n view.setUint16(\n offset + OFF_CLEAR_BYTES,\n isRbsp ? clearBytes | RBSP_FLAG : clearBytes,\n );\n dst[offset + OFF_VERSION] = E2EE_VERSION;\n view.setUint32(offset + OFF_MAGIC, MAGIC);\n };\n /**\n * IV fields only, from an already-recognized trailer. An H264 RBSP frame\n * escapes these three with the ciphertext, so un-escape the unit before\n * calling this.\n */\n const readTrailerIv = (buf) => {\n const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);\n const start = buf.length - TRAILER_LEN;\n return {\n frameCounter: view.getUint32(start),\n ivPrefix: buf.subarray(start + OFF_IV_PREFIX, start + OFF_KEY_INDEX),\n keyIndex: buf[start + OFF_KEY_INDEX],\n };\n };\n /**\n * The frozen identification suffix: `version (1) || magic (4)`. A literal, not\n * `TRAILER_LEN - OFF_VERSION`, because this length is frozen at 5 for every\n * version present and future while those two constants describe v1 only - a\n * later layout change must break the round-trip test, not silently move the\n * suffix older receivers depend on. `trailer.test.ts` pins it to the bytes\n * `writeTrailer` actually emits.\n *\n * Read from the end rather than from a trailer start, because a future version\n * may not use a 20-byte trailer, and a receiver that cannot decrypt such a\n * frame still has to recognize it.\n */\n const IDENT_SUFFIX_LEN = 5;\n /** Within the suffix: the magic follows the single version byte. */\n const OFF_SUFFIX_MAGIC = 1;\n /**\n * The framing version of a frame carrying this format, or `null` if the frame\n * is not ours at all.\n *\n * This is what separates the two reasons {@link readTrailer} returns `null`:\n * an unrelated cleartext frame, versus an encrypted frame from a peer on a\n * version this build cannot decrypt.\n *\n * @param view - An existing view over exactly `src`, to avoid a second\n * allocation on the per-frame decode path. Built here when omitted.\n */\n const readFramingVersion = (src, view) => {\n if (src.length < IDENT_SUFFIX_LEN) return null;\n const bytes =\n view ?? new DataView(src.buffer, src.byteOffset, src.byteLength);\n const start = src.length - IDENT_SUFFIX_LEN;\n if (bytes.getUint32(start + OFF_SUFFIX_MAGIC) !== MAGIC) return null;\n return src[start];\n };\n const readTrailer = (src) => {\n if (src.length < TRAILER_LEN) return null;\n const view = new DataView(src.buffer, src.byteOffset, src.byteLength);\n if (readFramingVersion(src, view) !== E2EE_VERSION) return null;\n const start = src.length - TRAILER_LEN;\n const raw = view.getUint16(start + OFF_CLEAR_BYTES);\n const clearBytes = raw & MAX_CLEAR_BYTES;\n // Bail out before allocating; the decrypt would fail anyway.\n if (clearBytes > src.length - TRAILER_LEN) return null;\n // The last 7 bytes survive escaping untouched: the RBSP flag holds the\n // clearBytes high byte >= 0x80 and breaks any zero run. The three below are\n // valid only on a non-RBSP frame; see {@link readTrailerIv}.\n return {\n frameCounter: view.getUint32(start),\n ivPrefix: src.subarray(start + OFF_IV_PREFIX, start + OFF_KEY_INDEX),\n keyIndex: src[start + OFF_KEY_INDEX],\n clearBytes,\n isRbsp: (raw & RBSP_FLAG) !== 0,\n };\n };\n\n /**\n * Monotonic, and deliberately shared across every track and codec this sender\n * publishes: the IV is `ivPrefix ∥ counter`, so two tracks drawing from\n * separate counters would encrypt different frames under the same IV.\n *\n * Survives `removeAllKeys` on purpose - if the same raw key is imported again the\n * counter keeps climbing, so no (ivPrefix, counter) pair repeats. Second guard\n * against IV reuse, after the per-import random prefix.\n */\n let counter = 0;\n const nextFrameCounter = () => {\n const next = counter + 1;\n if (next > COUNTER_HARD_LIMIT) {\n throw new Error(\n 'frame counter exhausted, create a new EncryptionManager',\n );\n }\n counter = next;\n return next;\n };\n\n const encodeTransform = (userId, codec, trackType) => {\n const profile = getCodecProfile(codec);\n const isNalu = profile.rbsp;\n // trackType is unique per sender; fall back to codec when it is unlabeled.\n const trackKey = trackType ?? codec ?? 'unknown';\n const codecKey = codec ?? 'unknown';\n const stats = encodeStats.track(trackKey, {\n userId,\n trackType: trackKey,\n codec: codecKey,\n });\n const notify = new EncodeNotifier(userId, trackType);\n const iv = new Uint8Array(IV_LEN);\n const ivView = new DataView(iv.buffer);\n /**\n * Times the encryption, emits the frame, reports failures. `produce` returns\n * the new bytes, or null when it already dropped the frame with its own\n * reason. Any throw drops the frame; it is never emitted in the clear.\n */\n const finishEncode = async (frame, controller, produce) => {\n try {\n const t0 = stats.startCrypto();\n const out = await produce();\n stats.endCrypto(t0);\n if (!out) return;\n frame.data = out.buffer;\n controller.enqueue(frame);\n notify.recovered();\n stats.bump();\n } catch (err) {\n notify.failed(err?.message || String(err));\n }\n };\n return new TransformStream({\n async transform(frame, controller) {\n // No payload to encrypt.\n if (frame.data.byteLength === 0) {\n controller.enqueue(frame);\n stats.bump();\n return;\n }\n const entry = keyStore.getLatestKey(userId);\n if (!entry) {\n notifyMissingEncodeKey(userId);\n return;\n }\n const { key: cryptoKey, keyIndex, ivPrefix: prefix } = entry;\n return finishEncode(frame, controller, async () => {\n // A key/delta type marks a video frame. An audio-only profile has no\n // clear-byte rule for one, so drop it rather than ship a whole-frame,\n // unescaped encrypt the SFU cannot read and a NALU packetizer would\n // split. Checked before the counter, so a dropped frame costs no IV.\n if (profile.audioOnly && frame.type !== undefined) {\n notify.failed(`no clear-byte rule for video on codec ${codecKey}`);\n return null;\n }\n const src = new Uint8Array(frame.data);\n const clearBytes = profile.clearBytes(frame.type, src);\n if (clearBytes > MAX_CLEAR_BYTES) {\n // Writing this would overflow into the RBSP flag bit.\n notify.failed('clearBytes exceeds trailer capacity');\n return null;\n }\n // Throws at the 32-bit ceiling; finishEncode catches it, so the track\n // fails closed instead of reusing an IV.\n const counter = nextFrameCounter();\n fillIV(iv, ivView, prefix, counter);\n const aad = clearBytes > 0 ? src.subarray(0, clearBytes) : EMPTY_AAD;\n const plaintext = clearBytes > 0 ? src.subarray(clearBytes) : src;\n const encrypted = await crypto.subtle.encrypt(\n { name: 'AES-GCM', iv, additionalData: aad },\n cryptoKey,\n plaintext,\n );\n const ciphertext = new Uint8Array(encrypted);\n if (isNalu && clearBytes > 0) {\n // Escape ciphertext and trailer as one unit: random ciphertext or\n // the counter bytes could otherwise form a fake Annex-B start code\n // that libwebrtc's H264 packetizer would split on. The escaper is\n // seeded with the clear header's trailing zeros so a start code\n // cannot form across the clear/encrypted boundary either.\n //\n // The last 7 trailer bytes survive escaping untouched: the RBSP flag\n // holds the clearBytes high byte at >= 0x80, which breaks any zero\n // run before it can reach them. The decoder reads them off the raw\n // frame tail to locate the unit.\n //\n // Escaping straight behind the clear header copies the ciphertext\n // once, instead of staging it through an intermediate unit buffer\n // and copying it again.\n const trailer = new Uint8Array(TRAILER_LEN);\n writeTrailer(\n trailer,\n 0,\n counter,\n prefix,\n keyIndex,\n clearBytes,\n true,\n );\n const body = [ciphertext, trailer];\n const seed = boundarySeedZeros(aad);\n const dst = new Uint8Array(\n clearBytes + rbspEscapedLength(body, seed),\n );\n dst.set(aad, 0);\n rbspEscapeInto(dst, clearBytes, body, seed);\n return dst;\n }\n const dst = new Uint8Array(\n clearBytes + ciphertext.length + TRAILER_LEN,\n );\n if (clearBytes > 0) dst.set(aad, 0);\n dst.set(ciphertext, clearBytes);\n writeTrailer(\n dst,\n clearBytes + ciphertext.length,\n counter,\n prefix,\n keyIndex,\n clearBytes,\n false,\n );\n return dst;\n });\n },\n });\n };\n\n /**\n * Consecutive decryption failures on one track, keyed by keyIndex so a rotation\n * starts fresh.\n */\n class FailureTracker {\n counts = new Map();\n /**\n * True only on the failure crossing {@link FAILURE_TOLERANCE}, so\n * `e2ee.decryption_stalled` fires once per run.\n */\n recordFailure = (keyIndex) => {\n const next = (this.counts.get(keyIndex) ?? 0) + 1;\n this.counts.set(keyIndex, next);\n return next === FAILURE_TOLERANCE + 1;\n };\n /**\n * True if there was a count to clear. Do NOT gate `e2ee.decryption_resumed`\n * on it: that event names a track, not a key epoch, so a track recovering on\n * a new keyIndex must still clear it.\n */\n recordSuccess = (keyIndex) => this.counts.delete(keyIndex);\n }\n\n /** Length-safe byte comparison, for matching a frame's prefix to an epoch. */\n const bytesEqual = (a, b) => {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;\n return true;\n };\n const REPLAY_WINDOW_WORDS = REPLAY_WINDOW >>> 5;\n /**\n * One sender IV-prefix epoch: a high-water mark plus a bitmap over the\n * preceding {@link REPLAY_WINDOW} counters, where bit `counter % REPLAY_WINDOW`\n * marks a seen counter. O(1) checks and in-order advance, where a `Set` would\n * need an O(REPLAY_WINDOW) prune per frame.\n */\n class ReplayEpoch {\n /** Copied, since the caller's view points into a frame buffer that is reused. */\n prefix;\n highest;\n bitmap = new Uint32Array(REPLAY_WINDOW_WORDS);\n constructor(prefix, counter) {\n this.prefix = prefix.slice();\n this.highest = counter;\n this.mark(counter);\n }\n /** Above the high-water mark, or inside the window and not yet seen. */\n accepts = (counter) => {\n if (counter > this.highest) return true;\n if (counter <= this.highest - REPLAY_WINDOW) return false;\n return !this.isMarked(counter);\n };\n record = (counter) => {\n if (counter > this.highest) {\n // Slots repeat every REPLAY_WINDOW counters, so skipped ones can hold a\n // stale bit and must be cleared. In-order frames skip none; a large jump\n // makes the whole bitmap stale.\n if (counter - this.highest >= REPLAY_WINDOW) {\n this.bitmap.fill(0);\n } else {\n for (let c = this.highest + 1; c < counter; c++) this.clear(c);\n }\n this.highest = counter;\n }\n this.mark(counter);\n };\n slot = (counter) => {\n const idx = counter % REPLAY_WINDOW;\n return { word: idx >>> 5, mask: 1 << (idx & 31) };\n };\n isMarked = (counter) => {\n const { word, mask } = this.slot(counter);\n return (this.bitmap[word] & mask) !== 0;\n };\n mark = (counter) => {\n const { word, mask } = this.slot(counter);\n this.bitmap[word] |= mask;\n };\n clear = (counter) => {\n const { word, mask } = this.slot(counter);\n this.bitmap[word] &= ~mask;\n };\n }\n /**\n * Sender IV-prefix \"epochs\" one track's guard keeps. One is normal; a second or\n * third appears briefly around a key re-import or sender restart, while old and\n * new prefixes interleave in the jitter buffer.\n *\n * Eviction is safe because the sender never reuses an (ivPrefix, counter) pair.\n * Only `commit` creates and evicts epochs, and only authenticated frames reach\n * it, so a relay cannot forge new-prefix frames to evict a genuine epoch.\n */\n const REPLAY_EPOCHS = 3;\n /**\n * Replay guard for one remote track.\n *\n * Shared across tracks it would couple them: independent SSRCs and jitter\n * buffers mean delivery skew could advance the high-water mark far enough to\n * reject a lagging track's frames, dropping media and reporting false failures.\n *\n * Inside a track the sender's IV prefix partitions the window further, so a\n * sender restart (fresh prefix, counter near 0) opens a clean window instead of\n * losing its low counters to a stale mark.\n *\n * Only receive-side bookkeeping is per track. The sender's counter stays global\n * per user (see `frameCounter.ts`), which is what keeps IVs unique across a\n * user's tracks and the wire format identical for other SDKs.\n */\n class ReplayWindow {\n epochs = [];\n find = (ivPrefix) =>\n this.epochs.find((e) => bytesEqual(e.prefix, ivPrefix));\n /**\n * True when this prefix can accept `counter`: new prefix, above the\n * high-water mark, or inside the window and not yet committed.\n *\n * Changes no state. A relay can forge the trailer fields this reads, so only\n * an authenticated frame advances the window. See {@link commit}.\n */\n peek = (counter, ivPrefix) => {\n // A prefix with no committed frame yet opens a clean window.\n return this.find(ivPrefix)?.accepts(counter) ?? true;\n };\n /**\n * Record `counter` as seen, advancing the high-water mark. Call it only after\n * AES-GCM authenticates, so unauthenticated bytes cannot wedge the window or\n * evict a genuine epoch.\n */\n commit = (counter, ivPrefix) => {\n const epoch = this.find(ivPrefix);\n if (epoch) {\n epoch.record(counter);\n return;\n }\n this.epochs.unshift(new ReplayEpoch(ivPrefix, counter));\n if (this.epochs.length > REPLAY_EPOCHS) this.epochs.pop();\n };\n }\n\n const decodeTransform = (userId, trackType) => {\n // Counts a peer's audio and video apart.\n const trackKey = trackType ?? 'unknown';\n const stats = decodeStats.track(`${userId}/${trackKey}`, {\n userId,\n trackType: trackKey,\n });\n const notify = new DecodeNotifier(userId, trackType);\n const iv = new Uint8Array(IV_LEN);\n const ivView = new DataView(iv.buffer);\n // Per track, so a user's audio, video and screen share never share a window\n // or a failure count. The separate count is what lets\n // e2ee.decryption_stalled fire.\n const replay = new ReplayWindow();\n const failures = new FailureTracker();\n /**\n * Gates on key and replay, decrypts, emits, then records failure or recovery.\n * `decrypt` throws on a GCM tag failure, dropping the frame. Separate from\n * the framing parse so the trust ordering lives in one place.\n *\n * Trust ordering (the SFrame/SRTP rule): a relay can forge `frameCounter`,\n * `ivPrefix` and `keyIndex`, which are plaintext in the trailer, so nothing\n * changes trust state until GCM authenticates. Hence peek before, commit\n * after. The failure counter is diagnostic only - it gates `e2ee.decryption_stalled`,\n * never the decrypt attempt - so forged frames cannot mark a key invalid.\n */\n const finishDecode = async (\n frame,\n controller,\n keyIndex,\n ivPrefix,\n frameCounter,\n decrypt,\n ) => {\n const cryptoKey = keyStore.getKey(userId, keyIndex);\n if (!cryptoKey) {\n notify.missingKey(keyIndex);\n return;\n }\n // No state change. A replay or an out-of-window frame is dropped silently;\n // neither is a decryption failure.\n if (!replay.peek(frameCounter, ivPrefix)) return;\n try {\n const t0 = stats.startCrypto();\n const data = await decrypt(cryptoKey);\n stats.endCrypto(t0);\n // Authenticated: only now is it safe to advance the replay window.\n replay.commit(frameCounter, ivPrefix);\n // Independent on purpose: the count is per keyIndex, but\n // `decryption_failed` is per track, so a track recovering on a NEW\n // keyIndex must still clear it. Gating on recordSuccess would latch the\n // host on failed forever.\n failures.recordSuccess(keyIndex);\n notify.resumed();\n frame.data = data;\n controller.enqueue(frame);\n stats.bump();\n } catch {\n // True only on the failure crossing the tolerance, so\n // `e2ee.decryption_stalled` fires once per run, not once per frame.\n const stalled = failures.recordFailure(keyIndex);\n notify.failed();\n if (stalled) notify.stalled(keyIndex);\n }\n };\n return new TransformStream({\n async transform(frame, controller) {\n if (frame.data.byteLength === 0) {\n controller.enqueue(frame);\n stats.bump();\n return;\n }\n const src = new Uint8Array(frame.data);\n const trailer = readTrailer(src);\n if (!trailer) {\n // Ours but unreadable: drop rather than forward. Handing ciphertext to\n // the decoder renders corruption and reads to the host as a downgrade,\n // when the actual condition is that this build is the older one.\n const version = readFramingVersion(src);\n if (version !== null && version !== E2EE_VERSION) {\n notify.unsupportedVersion(version);\n return;\n }\n notify.unencrypted();\n controller.enqueue(frame);\n stats.bump();\n return;\n }\n const { clearBytes, isRbsp } = trailer;\n // An RBSP (H264) frame escaped the ciphertext together with the counter,\n // ivPrefix and keyIndex, so un-escape to recover them; only the trailer\n // tail read above stayed clear. A non-RBSP frame keeps the trailer raw.\n let { frameCounter, ivPrefix, keyIndex } = trailer;\n let ciphertext;\n if (isRbsp) {\n // Same boundary seed as the encoder, derived from the same clear bytes.\n const seed = boundarySeedZeros(src.subarray(0, clearBytes));\n const unit = rbspUnescape(src.subarray(clearBytes), seed);\n // Un-escaping can leave less than a trailer, since readTrailer sized\n // clearBytes against the raw frame. A negative offset would throw out\n // of transform() and kill this track's pipeline for the session, and a\n // relay can forge the shape: clearBytes and the flag are plaintext.\n if (unit.length < TRAILER_LEN) return;\n ({ frameCounter, ivPrefix, keyIndex } = readTrailerIv(unit));\n ciphertext = unit.subarray(0, unit.length - TRAILER_LEN);\n } else {\n ciphertext = src.subarray(clearBytes, src.length - TRAILER_LEN);\n }\n return finishDecode(\n frame,\n controller,\n keyIndex,\n ivPrefix,\n frameCounter,\n async (key) => {\n fillIV(iv, ivView, ivPrefix, frameCounter);\n const aad =\n clearBytes > 0 ? src.subarray(0, clearBytes) : EMPTY_AAD;\n const decrypted = await crypto.subtle.decrypt(\n { name: 'AES-GCM', iv, additionalData: aad },\n key,\n ciphertext,\n );\n if (clearBytes === 0) return decrypted;\n const plaintext = new Uint8Array(decrypted);\n const dst = new Uint8Array(clearBytes + plaintext.length);\n dst.set(src.subarray(0, clearBytes), 0);\n dst.set(plaintext, clearBytes);\n return dst.buffer;\n },\n );\n },\n });\n };\n\n /**\n * E2EE Web Worker entry point. Owns the worker's message interface and wires\n * the encrypt/decrypt transforms into WebRTC Encoded Transforms. The main\n * thread distributes keys by postMessage, and transforms look one up per frame\n * by (userId, keyIndex).\n *\n * ## Wire format\n *\n * Frame layout is [clear header][ciphertext + GCM tag][20B trailer], so 36\n * bytes of overhead. The trailer holds:\n * [4B frameCounter][8B ivPrefix][1B keyIndex][2B clearBytes|flags]\n * [1B version][4B 0xE2EEFEED]\n *\n * The clear header keeps codec headers readable so the SFU can detect keyframes\n * and select layers: 1 byte for Opus, 10/3 for VP8 and VP9 (key/delta), and for\n * H264 everything up to the first slice NALU + 2, with the encrypted tail\n * RBSP-escaped against fake start codes. It doubles as the AAD, so the SFU can\n * read it but decrypt still detects tampering.\n *\n * The 12-byte IV is [ivPrefix][frameCounter]. `ivPrefix` is random per key\n * import and travels in the trailer, so IVs stay unique even when the host\n * imports the same raw key twice.\n *\n * rollup-plugin-inline-worker bundles this into the function\n * `../e2ee-worker.ts` exports.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Using_Encoded_Transforms\n * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/encrypt#aes-gcm\n */\n /**\n * Decode always runs. An encode whose codec the worker cannot split fails\n * closed: it still installs a transform, but one that drops every frame, since\n * returning without one leaves the encoder buffering forever with no signal.\n */\n const selectTransform = (operation, userId, codec, trackType) => {\n if (operation !== 'encode') return decodeTransform(userId, trackType);\n if (isSupportedCodec(codec))\n return encodeTransform(userId, codec, trackType);\n new EncodeNotifier(userId, trackType).failed(\n `unsupported codec for E2EE: ${codec}`,\n );\n // Enqueues nothing: every frame is dropped.\n return new TransformStream({ transform() {} });\n };\n const setupTransform = ({\n readable,\n writable,\n operation,\n userId,\n codec,\n trackType,\n }) => {\n const transform = selectTransform(operation, userId, codec, trackType);\n readable\n .pipeThrough(transform)\n .pipeTo(writable)\n .catch((err) => {\n reportError(\n `Transform pipeline error (${operation}, ${userId}): ${err?.message || err}`,\n );\n });\n };\n addEventListener('rtctransform', (event) => {\n const { readable, writable, options } = event.transformer;\n // Same queue as message-based setup, so an in-flight key import completes\n // before the transform is wired up.\n enqueue(async () => {\n setupTransform({ readable, writable, ...options });\n }).catch((err) => {\n reportError(`Transform setup failed: ${err?.message || err}`);\n });\n });\n addEventListener('message', ({ data }) => {\n enqueue(async () => {\n switch (data.type) {\n case 'cmd.set_key':\n await keyStore.importKey(data.userId, data.keyIndex, data.rawKey);\n break;\n case 'cmd.set_shared_key':\n await keyStore.importSharedKey(data.keyIndex, data.rawKey);\n break;\n case 'cmd.remove_shared_key':\n keyStore.removeSharedKey(data.keyIndex);\n break;\n case 'cmd.remove_key':\n // Deliberately keeps this user's decode stats: they are still\n // publishing, one epoch was retired.\n keyStore.removeKey(data.userId, data.keyIndex);\n break;\n case 'cmd.remove_all_keys':\n keyStore.removeAllKeys(data.userId);\n decodeStats.removeUser(data.userId);\n break;\n case 'cmd.enable_performance_reporting':\n if (data.enabled) startPerfReport();\n else stopPerfReport();\n break;\n case 'cmd.request_key_state':\n self.postMessage({ type: 'e2ee.key_state', ...keyStore.keyState() });\n break;\n case 'cmd.setup_transform':\n setupTransform(data);\n break;\n default:\n reportError(`Unknown command type: ${data.type}`);\n break;\n }\n }).catch((err) => {\n reportError(`Message handler error: ${err?.message || err}`);\n });\n });\n}\n"],"names":[],"mappings":"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"}
|