livekit-client 2.0.10 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +203 -140
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +12826 -15828
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.umd.js +1 -1
  8. package/dist/livekit-client.umd.js.map +1 -1
  9. package/dist/src/api/SignalClient.d.ts +2 -1
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/connectionHelper/ConnectionCheck.d.ts +3 -2
  12. package/dist/src/connectionHelper/ConnectionCheck.d.ts.map +1 -1
  13. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  14. package/dist/src/index.d.ts +3 -2
  15. package/dist/src/index.d.ts.map +1 -1
  16. package/dist/src/room/PCTransport.d.ts.map +1 -1
  17. package/dist/src/room/RTCEngine.d.ts +3 -3
  18. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  19. package/dist/src/room/events.d.ts +5 -1
  20. package/dist/src/room/events.d.ts.map +1 -1
  21. package/dist/src/room/participant/LocalParticipant.d.ts +1 -0
  22. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  23. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  24. package/dist/src/room/track/LocalAudioTrack.d.ts +7 -0
  25. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  26. package/dist/src/room/track/LocalTrackPublication.d.ts +3 -2
  27. package/dist/src/room/track/LocalTrackPublication.d.ts.map +1 -1
  28. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  29. package/dist/src/room/track/Track.d.ts +2 -1
  30. package/dist/src/room/track/Track.d.ts.map +1 -1
  31. package/dist/src/room/track/options.d.ts +1 -1
  32. package/dist/src/room/track/options.d.ts.map +1 -1
  33. package/dist/src/room/utils.d.ts +4 -1
  34. package/dist/src/room/utils.d.ts.map +1 -1
  35. package/dist/src/utils/browserParser.d.ts +1 -0
  36. package/dist/src/utils/browserParser.d.ts.map +1 -1
  37. package/dist/ts4.2/src/api/SignalClient.d.ts +2 -1
  38. package/dist/ts4.2/src/connectionHelper/ConnectionCheck.d.ts +3 -2
  39. package/dist/ts4.2/src/index.d.ts +3 -2
  40. package/dist/ts4.2/src/room/RTCEngine.d.ts +3 -3
  41. package/dist/ts4.2/src/room/events.d.ts +5 -1
  42. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +1 -0
  43. package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +7 -0
  44. package/dist/ts4.2/src/room/track/LocalTrackPublication.d.ts +3 -2
  45. package/dist/ts4.2/src/room/track/Track.d.ts +2 -1
  46. package/dist/ts4.2/src/room/track/options.d.ts +1 -1
  47. package/dist/ts4.2/src/room/utils.d.ts +4 -1
  48. package/dist/ts4.2/src/utils/browserParser.d.ts +1 -0
  49. package/package.json +10 -10
  50. package/src/api/SignalClient.ts +9 -0
  51. package/src/connectionHelper/ConnectionCheck.ts +6 -3
  52. package/src/e2ee/worker/FrameCryptor.ts +0 -1
  53. package/src/e2ee/worker/e2ee.worker.ts +3 -1
  54. package/src/index.ts +3 -0
  55. package/src/room/PCTransport.ts +0 -2
  56. package/src/room/RTCEngine.ts +18 -62
  57. package/src/room/events.ts +5 -0
  58. package/src/room/participant/LocalParticipant.ts +17 -5
  59. package/src/room/participant/publishUtils.ts +2 -1
  60. package/src/room/track/LocalAudioTrack.ts +40 -0
  61. package/src/room/track/LocalTrackPublication.ts +28 -2
  62. package/src/room/track/LocalVideoTrack.ts +7 -3
  63. package/src/room/track/Track.ts +13 -0
  64. package/src/room/track/options.ts +22 -1
  65. package/src/room/utils.ts +32 -27
  66. package/src/utils/browserParser.test.ts +4 -0
  67. package/src/utils/browserParser.ts +11 -1
@@ -55,6 +55,8 @@ var loglevel = {exports: {}};
55
55
  var undefinedType = "undefined";
56
56
  var isIE = typeof window !== undefinedType && typeof window.navigator !== undefinedType && /Trident\/|MSIE /.test(window.navigator.userAgent);
57
57
  var logMethods = ["trace", "debug", "info", "warn", "error"];
58
+ var _loggersByName = {};
59
+ var defaultLogger = null;
58
60
 
59
61
  // Cross-browser bind equivalent that works at least back to IE6
60
62
  function bindMethod(obj, methodName) {
@@ -107,23 +109,31 @@ var loglevel = {exports: {}};
107
109
 
108
110
  // These private functions always need `this` to be set properly
109
111
 
110
- function replaceLoggingMethods(level, loggerName) {
112
+ function replaceLoggingMethods() {
111
113
  /*jshint validthis:true */
114
+ var level = this.getLevel();
115
+
116
+ // Replace the actual methods.
112
117
  for (var i = 0; i < logMethods.length; i++) {
113
118
  var methodName = logMethods[i];
114
- this[methodName] = i < level ? noop : this.methodFactory(methodName, level, loggerName);
119
+ this[methodName] = i < level ? noop : this.methodFactory(methodName, level, this.name);
115
120
  }
116
121
 
117
122
  // Define log.log as an alias for log.debug
118
123
  this.log = this.debug;
124
+
125
+ // Return any important warnings.
126
+ if (typeof console === undefinedType && level < this.levels.SILENT) {
127
+ return "No console available for logging";
128
+ }
119
129
  }
120
130
 
121
131
  // In old IE versions, the console isn't present until you first open it.
122
132
  // We build realMethod() replacements here that regenerate logging methods
123
- function enableLoggingWhenConsoleArrives(methodName, level, loggerName) {
133
+ function enableLoggingWhenConsoleArrives(methodName) {
124
134
  return function () {
125
135
  if (typeof console !== undefinedType) {
126
- replaceLoggingMethods.call(this, level, loggerName);
136
+ replaceLoggingMethods.call(this);
127
137
  this[methodName].apply(this, arguments);
128
138
  }
129
139
  };
@@ -131,14 +141,34 @@ var loglevel = {exports: {}};
131
141
 
132
142
  // By default, we use closely bound real methods wherever possible, and
133
143
  // otherwise we wait for a console to appear, and then try again.
134
- function defaultMethodFactory(methodName, level, loggerName) {
144
+ function defaultMethodFactory(methodName, _level, _loggerName) {
135
145
  /*jshint validthis:true */
136
146
  return realMethod(methodName) || enableLoggingWhenConsoleArrives.apply(this, arguments);
137
147
  }
138
- function Logger(name, defaultLevel, factory) {
148
+ function Logger(name, factory) {
149
+ // Private instance variables.
139
150
  var self = this;
140
- var currentLevel;
141
- defaultLevel = defaultLevel == null ? "WARN" : defaultLevel;
151
+ /**
152
+ * The level inherited from a parent logger (or a global default). We
153
+ * cache this here rather than delegating to the parent so that it stays
154
+ * in sync with the actual logging methods that we have installed (the
155
+ * parent could change levels but we might not have rebuilt the loggers
156
+ * in this child yet).
157
+ * @type {number}
158
+ */
159
+ var inheritedLevel;
160
+ /**
161
+ * The default level for this logger, if any. If set, this overrides
162
+ * `inheritedLevel`.
163
+ * @type {number|null}
164
+ */
165
+ var defaultLevel;
166
+ /**
167
+ * A user-specific level for this logger. If set, this overrides
168
+ * `defaultLevel`.
169
+ * @type {number|null}
170
+ */
171
+ var userLevel;
142
172
  var storageKey = "loglevel";
143
173
  if (typeof name === "string") {
144
174
  storageKey += ":" + name;
@@ -171,9 +201,10 @@ var loglevel = {exports: {}};
171
201
  if (typeof storedLevel === undefinedType) {
172
202
  try {
173
203
  var cookie = window.document.cookie;
174
- var location = cookie.indexOf(encodeURIComponent(storageKey) + "=");
204
+ var cookieName = encodeURIComponent(storageKey);
205
+ var location = cookie.indexOf(cookieName + "=");
175
206
  if (location !== -1) {
176
- storedLevel = /^([^;]+)/.exec(cookie.slice(location))[1];
207
+ storedLevel = /^([^;]+)/.exec(cookie.slice(location + cookieName.length + 1))[1];
177
208
  }
178
209
  } catch (ignore) {}
179
210
  }
@@ -190,7 +221,6 @@ var loglevel = {exports: {}};
190
221
  // Use localStorage if available
191
222
  try {
192
223
  window.localStorage.removeItem(storageKey);
193
- return;
194
224
  } catch (ignore) {}
195
225
 
196
226
  // Use session cookie as fallback
@@ -198,6 +228,17 @@ var loglevel = {exports: {}};
198
228
  window.document.cookie = encodeURIComponent(storageKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC";
199
229
  } catch (ignore) {}
200
230
  }
231
+ function normalizeLevel(input) {
232
+ var level = input;
233
+ if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
234
+ level = self.levels[level.toUpperCase()];
235
+ }
236
+ if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
237
+ return level;
238
+ } else {
239
+ throw new TypeError("log.setLevel() called with invalid level: " + input);
240
+ }
241
+ }
201
242
 
202
243
  /*
203
244
  *
@@ -216,35 +257,34 @@ var loglevel = {exports: {}};
216
257
  };
217
258
  self.methodFactory = factory || defaultMethodFactory;
218
259
  self.getLevel = function () {
219
- return currentLevel;
260
+ if (userLevel != null) {
261
+ return userLevel;
262
+ } else if (defaultLevel != null) {
263
+ return defaultLevel;
264
+ } else {
265
+ return inheritedLevel;
266
+ }
220
267
  };
221
268
  self.setLevel = function (level, persist) {
222
- if (typeof level === "string" && self.levels[level.toUpperCase()] !== undefined) {
223
- level = self.levels[level.toUpperCase()];
224
- }
225
- if (typeof level === "number" && level >= 0 && level <= self.levels.SILENT) {
226
- currentLevel = level;
227
- if (persist !== false) {
228
- // defaults to true
229
- persistLevelIfPossible(level);
230
- }
231
- replaceLoggingMethods.call(self, level, name);
232
- if (typeof console === undefinedType && level < self.levels.SILENT) {
233
- return "No console available for logging";
234
- }
235
- } else {
236
- throw "log.setLevel() called with invalid level: " + level;
269
+ userLevel = normalizeLevel(level);
270
+ if (persist !== false) {
271
+ // defaults to true
272
+ persistLevelIfPossible(userLevel);
237
273
  }
274
+
275
+ // NOTE: in v2, this should call rebuild(), which updates children.
276
+ return replaceLoggingMethods.call(self);
238
277
  };
239
278
  self.setDefaultLevel = function (level) {
240
- defaultLevel = level;
279
+ defaultLevel = normalizeLevel(level);
241
280
  if (!getPersistedLevel()) {
242
281
  self.setLevel(level, false);
243
282
  }
244
283
  };
245
284
  self.resetLevel = function () {
246
- self.setLevel(defaultLevel, false);
285
+ userLevel = null;
247
286
  clearPersistedLevel();
287
+ replaceLoggingMethods.call(self);
248
288
  };
249
289
  self.enableAll = function (persist) {
250
290
  self.setLevel(self.levels.TRACE, persist);
@@ -252,13 +292,25 @@ var loglevel = {exports: {}};
252
292
  self.disableAll = function (persist) {
253
293
  self.setLevel(self.levels.SILENT, persist);
254
294
  };
295
+ self.rebuild = function () {
296
+ if (defaultLogger !== self) {
297
+ inheritedLevel = normalizeLevel(defaultLogger.getLevel());
298
+ }
299
+ replaceLoggingMethods.call(self);
300
+ if (defaultLogger === self) {
301
+ for (var childName in _loggersByName) {
302
+ _loggersByName[childName].rebuild();
303
+ }
304
+ }
305
+ };
255
306
 
256
- // Initialize with the right level
307
+ // Initialize all the internal levels.
308
+ inheritedLevel = normalizeLevel(defaultLogger ? defaultLogger.getLevel() : "WARN");
257
309
  var initialLevel = getPersistedLevel();
258
- if (initialLevel == null) {
259
- initialLevel = defaultLevel;
310
+ if (initialLevel != null) {
311
+ userLevel = normalizeLevel(initialLevel);
260
312
  }
261
- self.setLevel(initialLevel, false);
313
+ replaceLoggingMethods.call(self);
262
314
  }
263
315
 
264
316
  /*
@@ -267,15 +319,14 @@ var loglevel = {exports: {}};
267
319
  *
268
320
  */
269
321
 
270
- var defaultLogger = new Logger();
271
- var _loggersByName = {};
322
+ defaultLogger = new Logger();
272
323
  defaultLogger.getLogger = function getLogger(name) {
273
324
  if (typeof name !== "symbol" && typeof name !== "string" || name === "") {
274
325
  throw new TypeError("You must supply a name when creating a logger.");
275
326
  }
276
327
  var logger = _loggersByName[name];
277
328
  if (!logger) {
278
- logger = _loggersByName[name] = new Logger(name, defaultLogger.getLevel(), defaultLogger.methodFactory);
329
+ logger = _loggersByName[name] = new Logger(name, defaultLogger.methodFactory);
279
330
  }
280
331
  return logger;
281
332
  };
@@ -811,14 +862,16 @@ var eventsExports = events.exports;
811
862
  function isVideoFrame(frame) {
812
863
  return 'type' in frame;
813
864
  }
814
- function importKey(keyBytes) {
815
- let algorithm = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
816
- name: ENCRYPTION_ALGORITHM
817
- };
818
- let usage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'encrypt';
819
- return __awaiter(this, void 0, void 0, function* () {
820
- // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey
821
- return crypto.subtle.importKey('raw', keyBytes, algorithm, false, usage === 'derive' ? ['deriveBits', 'deriveKey'] : ['encrypt', 'decrypt']);
865
+ function importKey(keyBytes_1) {
866
+ return __awaiter(this, arguments, void 0, function (keyBytes) {
867
+ let algorithm = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {
868
+ name: ENCRYPTION_ALGORITHM
869
+ };
870
+ let usage = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'encrypt';
871
+ return function* () {
872
+ // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey
873
+ return crypto.subtle.importKey('raw', keyBytes, algorithm, false, usage === 'derive' ? ['deriveBits', 'deriveKey'] : ['encrypt', 'decrypt']);
874
+ }();
822
875
  });
823
876
  }
824
877
  function getAlgoOptions(algorithmName, salt) {
@@ -1091,8 +1144,8 @@ class FrameCryptor extends BaseFrameCryptor {
1091
1144
  * 9) Enqueue the encrypted frame for sending.
1092
1145
  */
1093
1146
  encodeFunction(encodedFrame, controller) {
1094
- var _a;
1095
1147
  return __awaiter(this, void 0, void 0, function* () {
1148
+ var _a;
1096
1149
  if (!this.isEnabled() ||
1097
1150
  // skip for encryption for empty dtx frames
1098
1151
  encodedFrame.data.byteLength === 0) {
@@ -1210,89 +1263,92 @@ class FrameCryptor extends BaseFrameCryptor {
1210
1263
  * Function that will decrypt the given encoded frame. If the decryption fails, it will
1211
1264
  * ratchet the key for up to RATCHET_WINDOW_SIZE times.
1212
1265
  */
1213
- decryptFrame(encodedFrame, keyIndex) {
1214
- let initialMaterial = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
1215
- let ratchetOpts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
1216
- ratchetCount: 0
1217
- };
1218
- var _a;
1219
- return __awaiter(this, void 0, void 0, function* () {
1220
- const keySet = this.keys.getKeySet(keyIndex);
1221
- if (!ratchetOpts.encryptionKey && !keySet) {
1222
- throw new TypeError("no encryption key found for decryption of ".concat(this.participantIdentity));
1223
- }
1224
- let frameInfo = this.getUnencryptedBytes(encodedFrame);
1225
- // Construct frame trailer. Similar to the frame header described in
1226
- // https://tools.ietf.org/html/draft-omara-sframe-00#section-4.2
1227
- // but we put it at the end.
1228
- //
1229
- // ---------+-------------------------+-+---------+----
1230
- // payload |IV...(length = IV_LENGTH)|R|IV_LENGTH|KID |
1231
- // ---------+-------------------------+-+---------+----
1232
- try {
1233
- const frameHeader = new Uint8Array(encodedFrame.data, 0, frameInfo.unencryptedBytes);
1234
- var encryptedData = new Uint8Array(encodedFrame.data, frameHeader.length, encodedFrame.data.byteLength - frameHeader.length);
1235
- if (frameInfo.isH264 && needsRbspUnescaping(encryptedData)) {
1236
- encryptedData = parseRbsp(encryptedData);
1237
- const newUint8 = new Uint8Array(frameHeader.byteLength + encryptedData.byteLength);
1238
- newUint8.set(frameHeader);
1239
- newUint8.set(encryptedData, frameHeader.byteLength);
1240
- encodedFrame.data = newUint8.buffer;
1266
+ decryptFrame(encodedFrame_1, keyIndex_1) {
1267
+ return __awaiter(this, arguments, void 0, function (encodedFrame, keyIndex) {
1268
+ var _this = this;
1269
+ let initialMaterial = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : undefined;
1270
+ let ratchetOpts = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {
1271
+ ratchetCount: 0
1272
+ };
1273
+ return function* () {
1274
+ var _a;
1275
+ const keySet = _this.keys.getKeySet(keyIndex);
1276
+ if (!ratchetOpts.encryptionKey && !keySet) {
1277
+ throw new TypeError("no encryption key found for decryption of ".concat(_this.participantIdentity));
1241
1278
  }
1242
- const frameTrailer = new Uint8Array(encodedFrame.data, encodedFrame.data.byteLength - 2, 2);
1243
- const ivLength = frameTrailer[0];
1244
- const iv = new Uint8Array(encodedFrame.data, encodedFrame.data.byteLength - ivLength - frameTrailer.byteLength, ivLength);
1245
- const cipherTextStart = frameHeader.byteLength;
1246
- const cipherTextLength = encodedFrame.data.byteLength - (frameHeader.byteLength + ivLength + frameTrailer.byteLength);
1247
- const plainText = yield crypto.subtle.decrypt({
1248
- name: ENCRYPTION_ALGORITHM,
1249
- iv,
1250
- additionalData: new Uint8Array(encodedFrame.data, 0, frameHeader.byteLength)
1251
- }, (_a = ratchetOpts.encryptionKey) !== null && _a !== void 0 ? _a : keySet.encryptionKey, new Uint8Array(encodedFrame.data, cipherTextStart, cipherTextLength));
1252
- const newData = new ArrayBuffer(frameHeader.byteLength + plainText.byteLength);
1253
- const newUint8 = new Uint8Array(newData);
1254
- newUint8.set(new Uint8Array(encodedFrame.data, 0, frameHeader.byteLength));
1255
- newUint8.set(new Uint8Array(plainText), frameHeader.byteLength);
1256
- encodedFrame.data = newData;
1257
- return encodedFrame;
1258
- } catch (error) {
1259
- if (this.keyProviderOptions.ratchetWindowSize > 0) {
1260
- if (ratchetOpts.ratchetCount < this.keyProviderOptions.ratchetWindowSize) {
1261
- workerLogger.debug("ratcheting key attempt ".concat(ratchetOpts.ratchetCount, " of ").concat(this.keyProviderOptions.ratchetWindowSize, ", for kind ").concat(encodedFrame instanceof RTCEncodedAudioFrame ? 'audio' : 'video'));
1262
- let ratchetedKeySet;
1263
- if ((initialMaterial !== null && initialMaterial !== void 0 ? initialMaterial : keySet) === this.keys.getKeySet(keyIndex)) {
1264
- // only ratchet if the currently set key is still the same as the one used to decrypt this frame
1265
- // if not, it might be that a different frame has already ratcheted and we try with that one first
1266
- const newMaterial = yield this.keys.ratchetKey(keyIndex, false);
1267
- ratchetedKeySet = yield deriveKeys(newMaterial, this.keyProviderOptions.ratchetSalt);
1268
- }
1269
- const frame = yield this.decryptFrame(encodedFrame, keyIndex, initialMaterial || keySet, {
1270
- ratchetCount: ratchetOpts.ratchetCount + 1,
1271
- encryptionKey: ratchetedKeySet === null || ratchetedKeySet === void 0 ? void 0 : ratchetedKeySet.encryptionKey
1272
- });
1273
- if (frame && ratchetedKeySet) {
1274
- // before updating the keys, make sure that the keySet used for this frame is still the same as the currently set key
1275
- // if it's not, a new key might have been set already, which we don't want to override
1276
- if ((initialMaterial !== null && initialMaterial !== void 0 ? initialMaterial : keySet) === this.keys.getKeySet(keyIndex)) {
1277
- this.keys.setKeySet(ratchetedKeySet, keyIndex, true);
1278
- // decryption was successful, set the new key index to reflect the ratcheted key set
1279
- this.keys.setCurrentKeyIndex(keyIndex);
1279
+ let frameInfo = _this.getUnencryptedBytes(encodedFrame);
1280
+ // Construct frame trailer. Similar to the frame header described in
1281
+ // https://tools.ietf.org/html/draft-omara-sframe-00#section-4.2
1282
+ // but we put it at the end.
1283
+ //
1284
+ // ---------+-------------------------+-+---------+----
1285
+ // payload |IV...(length = IV_LENGTH)|R|IV_LENGTH|KID |
1286
+ // ---------+-------------------------+-+---------+----
1287
+ try {
1288
+ const frameHeader = new Uint8Array(encodedFrame.data, 0, frameInfo.unencryptedBytes);
1289
+ var encryptedData = new Uint8Array(encodedFrame.data, frameHeader.length, encodedFrame.data.byteLength - frameHeader.length);
1290
+ if (frameInfo.isH264 && needsRbspUnescaping(encryptedData)) {
1291
+ encryptedData = parseRbsp(encryptedData);
1292
+ const newUint8 = new Uint8Array(frameHeader.byteLength + encryptedData.byteLength);
1293
+ newUint8.set(frameHeader);
1294
+ newUint8.set(encryptedData, frameHeader.byteLength);
1295
+ encodedFrame.data = newUint8.buffer;
1296
+ }
1297
+ const frameTrailer = new Uint8Array(encodedFrame.data, encodedFrame.data.byteLength - 2, 2);
1298
+ const ivLength = frameTrailer[0];
1299
+ const iv = new Uint8Array(encodedFrame.data, encodedFrame.data.byteLength - ivLength - frameTrailer.byteLength, ivLength);
1300
+ const cipherTextStart = frameHeader.byteLength;
1301
+ const cipherTextLength = encodedFrame.data.byteLength - (frameHeader.byteLength + ivLength + frameTrailer.byteLength);
1302
+ const plainText = yield crypto.subtle.decrypt({
1303
+ name: ENCRYPTION_ALGORITHM,
1304
+ iv,
1305
+ additionalData: new Uint8Array(encodedFrame.data, 0, frameHeader.byteLength)
1306
+ }, (_a = ratchetOpts.encryptionKey) !== null && _a !== void 0 ? _a : keySet.encryptionKey, new Uint8Array(encodedFrame.data, cipherTextStart, cipherTextLength));
1307
+ const newData = new ArrayBuffer(frameHeader.byteLength + plainText.byteLength);
1308
+ const newUint8 = new Uint8Array(newData);
1309
+ newUint8.set(new Uint8Array(encodedFrame.data, 0, frameHeader.byteLength));
1310
+ newUint8.set(new Uint8Array(plainText), frameHeader.byteLength);
1311
+ encodedFrame.data = newData;
1312
+ return encodedFrame;
1313
+ } catch (error) {
1314
+ if (_this.keyProviderOptions.ratchetWindowSize > 0) {
1315
+ if (ratchetOpts.ratchetCount < _this.keyProviderOptions.ratchetWindowSize) {
1316
+ workerLogger.debug("ratcheting key attempt ".concat(ratchetOpts.ratchetCount, " of ").concat(_this.keyProviderOptions.ratchetWindowSize, ", for kind ").concat(encodedFrame instanceof RTCEncodedAudioFrame ? 'audio' : 'video'));
1317
+ let ratchetedKeySet;
1318
+ if ((initialMaterial !== null && initialMaterial !== void 0 ? initialMaterial : keySet) === _this.keys.getKeySet(keyIndex)) {
1319
+ // only ratchet if the currently set key is still the same as the one used to decrypt this frame
1320
+ // if not, it might be that a different frame has already ratcheted and we try with that one first
1321
+ const newMaterial = yield _this.keys.ratchetKey(keyIndex, false);
1322
+ ratchetedKeySet = yield deriveKeys(newMaterial, _this.keyProviderOptions.ratchetSalt);
1280
1323
  }
1324
+ const frame = yield _this.decryptFrame(encodedFrame, keyIndex, initialMaterial || keySet, {
1325
+ ratchetCount: ratchetOpts.ratchetCount + 1,
1326
+ encryptionKey: ratchetedKeySet === null || ratchetedKeySet === void 0 ? void 0 : ratchetedKeySet.encryptionKey
1327
+ });
1328
+ if (frame && ratchetedKeySet) {
1329
+ // before updating the keys, make sure that the keySet used for this frame is still the same as the currently set key
1330
+ // if it's not, a new key might have been set already, which we don't want to override
1331
+ if ((initialMaterial !== null && initialMaterial !== void 0 ? initialMaterial : keySet) === _this.keys.getKeySet(keyIndex)) {
1332
+ _this.keys.setKeySet(ratchetedKeySet, keyIndex, true);
1333
+ // decryption was successful, set the new key index to reflect the ratcheted key set
1334
+ _this.keys.setCurrentKeyIndex(keyIndex);
1335
+ }
1336
+ }
1337
+ return frame;
1338
+ } else {
1339
+ /**
1340
+ * Because we only set a new key once decryption has been successful,
1341
+ * we can be sure that we don't need to reset the key to the initial material at this point
1342
+ * as the key has not been updated on the keyHandler instance
1343
+ */
1344
+ workerLogger.warn('maximum ratchet attempts exceeded');
1345
+ throw new CryptorError("valid key missing for participant ".concat(_this.participantIdentity), CryptorErrorReason.InvalidKey);
1281
1346
  }
1282
- return frame;
1283
1347
  } else {
1284
- /**
1285
- * Because we only set a new key once decryption has been successful,
1286
- * we can be sure that we don't need to reset the key to the initial material at this point
1287
- * as the key has not been updated on the keyHandler instance
1288
- */
1289
- workerLogger.warn('maximum ratchet attempts exceeded');
1290
- throw new CryptorError("valid key missing for participant ".concat(this.participantIdentity), CryptorErrorReason.InvalidKey);
1348
+ throw new CryptorError("Decryption failed: ".concat(error.message), CryptorErrorReason.InvalidKey);
1291
1349
  }
1292
- } else {
1293
- throw new CryptorError("Decryption failed: ".concat(error.message), CryptorErrorReason.InvalidKey);
1294
1350
  }
1295
- }
1351
+ }();
1296
1352
  });
1297
1353
  }
1298
1354
  /**
@@ -1388,7 +1444,6 @@ class FrameCryptor extends BaseFrameCryptor {
1388
1444
  if (this.rtpMap.size === 0) {
1389
1445
  return undefined;
1390
1446
  }
1391
- // @ts-expect-error payloadType is not yet part of the typescript definition and currently not supported in Safari
1392
1447
  const payloadType = frame.getMetadata().payloadType;
1393
1448
  const codec = payloadType ? this.rtpMap.get(payloadType) : undefined;
1394
1449
  return codec;
@@ -1572,11 +1627,14 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1572
1627
  * together with the material
1573
1628
  * also resets the valid key property and updates the currentKeyIndex
1574
1629
  */
1575
- setKey(material) {
1576
- let keyIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
1577
- return __awaiter(this, void 0, void 0, function* () {
1578
- yield this.setKeyFromMaterial(material, keyIndex);
1579
- this.resetKeyStatus();
1630
+ setKey(material_1) {
1631
+ return __awaiter(this, arguments, void 0, function (material) {
1632
+ var _this = this;
1633
+ let keyIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
1634
+ return function* () {
1635
+ yield _this.setKeyFromMaterial(material, keyIndex);
1636
+ _this.resetKeyStatus();
1637
+ }();
1580
1638
  });
1581
1639
  }
1582
1640
  /**
@@ -1585,18 +1643,21 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1585
1643
  * together with the material
1586
1644
  * also updates the currentKeyIndex
1587
1645
  */
1588
- setKeyFromMaterial(material, keyIndex) {
1589
- let emitRatchetEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1590
- return __awaiter(this, void 0, void 0, function* () {
1591
- const keySet = yield deriveKeys(material, this.keyProviderOptions.ratchetSalt);
1592
- const newIndex = keyIndex >= 0 ? keyIndex % this.cryptoKeyRing.length : this.currentKeyIndex;
1593
- workerLogger.debug("setting new key with index ".concat(keyIndex), {
1594
- usage: material.usages,
1595
- algorithm: material.algorithm,
1596
- ratchetSalt: this.keyProviderOptions.ratchetSalt
1597
- });
1598
- this.setKeySet(keySet, newIndex, emitRatchetEvent);
1599
- if (newIndex >= 0) this.currentKeyIndex = newIndex;
1646
+ setKeyFromMaterial(material_1, keyIndex_1) {
1647
+ return __awaiter(this, arguments, void 0, function (material, keyIndex) {
1648
+ var _this2 = this;
1649
+ let emitRatchetEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1650
+ return function* () {
1651
+ const keySet = yield deriveKeys(material, _this2.keyProviderOptions.ratchetSalt);
1652
+ const newIndex = keyIndex >= 0 ? keyIndex % _this2.cryptoKeyRing.length : _this2.currentKeyIndex;
1653
+ workerLogger.debug("setting new key with index ".concat(keyIndex), {
1654
+ usage: material.usages,
1655
+ algorithm: material.algorithm,
1656
+ ratchetSalt: _this2.keyProviderOptions.ratchetSalt
1657
+ });
1658
+ _this2.setKeySet(keySet, newIndex, emitRatchetEvent);
1659
+ if (newIndex >= 0) _this2.currentKeyIndex = newIndex;
1660
+ }();
1600
1661
  });
1601
1662
  }
1602
1663
  setKeySet(keySet, keyIndex) {
@@ -1831,8 +1892,10 @@ if (self.RTCTransformEvent) {
1831
1892
  workerLogger.debug('setup transform event');
1832
1893
  // @ts-ignore
1833
1894
  self.onrtctransform = event => {
1895
+ // @ts-ignore .transformer property is part of RTCTransformEvent
1834
1896
  const transformer = event.transformer;
1835
1897
  workerLogger.debug('transformer', transformer);
1898
+ // @ts-ignore monkey patching non standard flag
1836
1899
  transformer.handled = true;
1837
1900
  const {
1838
1901
  kind,