livekit-client 2.5.7 → 2.5.9

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.
Files changed (32) hide show
  1. package/README.md +2 -2
  2. package/dist/livekit-client.e2ee.worker.js +1 -1
  3. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  4. package/dist/livekit-client.e2ee.worker.mjs +53 -20
  5. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  6. package/dist/livekit-client.esm.mjs +39 -3
  7. package/dist/livekit-client.esm.mjs.map +1 -1
  8. package/dist/livekit-client.umd.js +1 -1
  9. package/dist/livekit-client.umd.js.map +1 -1
  10. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  11. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts +25 -5
  12. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts.map +1 -1
  13. package/dist/src/room/Room.d.ts +3 -1
  14. package/dist/src/room/Room.d.ts.map +1 -1
  15. package/dist/src/room/events.d.ts +5 -1
  16. package/dist/src/room/events.d.ts.map +1 -1
  17. package/dist/src/room/participant/LocalParticipant.d.ts +7 -0
  18. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  19. package/dist/ts4.2/src/e2ee/worker/ParticipantKeyHandler.d.ts +25 -5
  20. package/dist/ts4.2/src/room/Room.d.ts +3 -1
  21. package/dist/ts4.2/src/room/events.d.ts +5 -1
  22. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +7 -0
  23. package/package.json +7 -7
  24. package/src/e2ee/worker/FrameCryptor.test.ts +311 -113
  25. package/src/e2ee/worker/FrameCryptor.ts +10 -5
  26. package/src/e2ee/worker/ParticipantKeyHandler.test.ts +169 -5
  27. package/src/e2ee/worker/ParticipantKeyHandler.ts +50 -20
  28. package/src/e2ee/worker/__snapshots__/ParticipantKeyHandler.test.ts.snap +356 -0
  29. package/src/room/Room.ts +8 -0
  30. package/src/room/events.ts +5 -0
  31. package/src/room/participant/LocalParticipant.ts +26 -1
  32. package/src/room/track/LocalTrackPublication.ts +1 -1
@@ -4691,6 +4691,10 @@ var RoomEvent;
4691
4691
  * fired when the first remote participant has subscribed to the localParticipant's track
4692
4692
  */
4693
4693
  RoomEvent["LocalTrackSubscribed"] = "localTrackSubscribed";
4694
+ /**
4695
+ * fired when the client receives connection metrics from other participants
4696
+ */
4697
+ RoomEvent["MetricsReceived"] = "metricsReceived";
4694
4698
  })(RoomEvent || (RoomEvent = {}));
4695
4699
  var ParticipantEvent;
4696
4700
  (function (ParticipantEvent) {
@@ -5937,10 +5941,14 @@ class FrameCryptor extends BaseFrameCryptor {
5937
5941
  }
5938
5942
  const data = new Uint8Array(encodedFrame.data);
5939
5943
  const keyIndex = data[encodedFrame.data.byteLength - 1];
5940
- if (this.keys.getKeySet(keyIndex) && this.keys.hasValidKey) {
5944
+ if (this.keys.hasInvalidKeyAtIndex(keyIndex)) {
5945
+ // drop frame
5946
+ return;
5947
+ }
5948
+ if (this.keys.getKeySet(keyIndex)) {
5941
5949
  try {
5942
5950
  const decodedFrame = yield this.decryptFrame(encodedFrame, keyIndex);
5943
- this.keys.decryptionSuccess();
5951
+ this.keys.decryptionSuccess(keyIndex);
5944
5952
  if (decodedFrame) {
5945
5953
  return controller.enqueue(decodedFrame);
5946
5954
  }
@@ -5949,7 +5957,7 @@ class FrameCryptor extends BaseFrameCryptor {
5949
5957
  // emit an error if the key handler thinks we have a valid key
5950
5958
  if (this.keys.hasValidKey) {
5951
5959
  this.emit(CryptorEvent.Error, error);
5952
- this.keys.decryptionFailure();
5960
+ this.keys.decryptionFailure(keyIndex);
5953
5961
  }
5954
5962
  } else {
5955
5963
  workerLogger.warn('decoding frame failed', {
@@ -5957,11 +5965,11 @@ class FrameCryptor extends BaseFrameCryptor {
5957
5965
  });
5958
5966
  }
5959
5967
  }
5960
- } else if (!this.keys.getKeySet(keyIndex) && this.keys.hasValidKey) {
5968
+ } else {
5961
5969
  // emit an error if the key index is out of bounds but the key handler thinks we still have a valid key
5962
5970
  workerLogger.warn("skipping decryption due to missing key at index ".concat(keyIndex));
5963
5971
  this.emit(CryptorEvent.Error, new CryptorError("missing key at index ".concat(keyIndex, " for participant ").concat(this.participantIdentity), CryptorErrorReason.MissingKey, this.participantIdentity));
5964
- this.keys.decryptionFailure();
5972
+ this.keys.decryptionFailure(keyIndex);
5965
5973
  }
5966
5974
  });
5967
5975
  }
@@ -6255,43 +6263,68 @@ function isFrameServerInjected(frameData, trailerBytes) {
6255
6263
  *
6256
6264
  */
6257
6265
  class ParticipantKeyHandler extends eventsExports.EventEmitter {
6266
+ /**
6267
+ * true if the current key has not been marked as invalid
6268
+ */
6258
6269
  get hasValidKey() {
6259
- return this._hasValidKey;
6270
+ return !this.hasInvalidKeyAtIndex(this.currentKeyIndex);
6260
6271
  }
6261
6272
  constructor(participantIdentity, keyProviderOptions) {
6262
6273
  super();
6263
- this.decryptionFailureCount = 0;
6264
- this._hasValidKey = true;
6265
6274
  this.currentKeyIndex = 0;
6266
6275
  if (keyProviderOptions.keyringSize < 1 || keyProviderOptions.keyringSize > 256) {
6267
6276
  throw new TypeError('Keyring size needs to be between 1 and 256');
6268
6277
  }
6269
6278
  this.cryptoKeyRing = new Array(keyProviderOptions.keyringSize).fill(undefined);
6279
+ this.decryptionFailureCounts = new Array(keyProviderOptions.keyringSize).fill(0);
6270
6280
  this.keyProviderOptions = keyProviderOptions;
6271
6281
  this.ratchetPromiseMap = new Map();
6272
6282
  this.participantIdentity = participantIdentity;
6273
- this.resetKeyStatus();
6274
6283
  }
6284
+ /**
6285
+ * Returns true if the key at the given index is marked as invalid.
6286
+ *
6287
+ * @param keyIndex the index of the key
6288
+ */
6289
+ hasInvalidKeyAtIndex(keyIndex) {
6290
+ return this.keyProviderOptions.failureTolerance >= 0 && this.decryptionFailureCounts[keyIndex] > this.keyProviderOptions.failureTolerance;
6291
+ }
6292
+ /**
6293
+ * Informs the key handler that a decryption failure occurred for an encryption key.
6294
+ * @internal
6295
+ * @param keyIndex the key index for which the failure occurred. Defaults to the current key index.
6296
+ */
6275
6297
  decryptionFailure() {
6298
+ let keyIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.currentKeyIndex;
6276
6299
  if (this.keyProviderOptions.failureTolerance < 0) {
6277
6300
  return;
6278
6301
  }
6279
- this.decryptionFailureCount += 1;
6280
- if (this.decryptionFailureCount > this.keyProviderOptions.failureTolerance) {
6281
- workerLogger.warn("key for ".concat(this.participantIdentity, " is being marked as invalid"));
6282
- this._hasValidKey = false;
6302
+ this.decryptionFailureCounts[keyIndex] += 1;
6303
+ if (this.decryptionFailureCounts[keyIndex] > this.keyProviderOptions.failureTolerance) {
6304
+ workerLogger.warn("key for ".concat(this.participantIdentity, " at index ").concat(keyIndex, " is being marked as invalid"));
6283
6305
  }
6284
6306
  }
6307
+ /**
6308
+ * Informs the key handler that a frame was successfully decrypted using an encryption key.
6309
+ * @internal
6310
+ * @param keyIndex the key index for which the success occurred. Defaults to the current key index.
6311
+ */
6285
6312
  decryptionSuccess() {
6286
- this.resetKeyStatus();
6313
+ let keyIndex = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.currentKeyIndex;
6314
+ this.resetKeyStatus(keyIndex);
6287
6315
  }
6288
6316
  /**
6289
6317
  * Call this after user initiated ratchet or a new key has been set in order to make sure to mark potentially
6290
6318
  * invalid keys as valid again
6319
+ *
6320
+ * @param keyIndex the index of the key. Defaults to the current key index.
6291
6321
  */
6292
- resetKeyStatus() {
6293
- this.decryptionFailureCount = 0;
6294
- this._hasValidKey = true;
6322
+ resetKeyStatus(keyIndex) {
6323
+ if (keyIndex === undefined) {
6324
+ this.decryptionFailureCounts.fill(0);
6325
+ } else {
6326
+ this.decryptionFailureCounts[keyIndex] = 0;
6327
+ }
6295
6328
  }
6296
6329
  /**
6297
6330
  * Ratchets the current key (or the one at keyIndex if provided) and
@@ -6316,7 +6349,7 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
6316
6349
  const currentMaterial = keySet.material;
6317
6350
  const newMaterial = yield importKey(yield ratchet(currentMaterial, this.keyProviderOptions.ratchetSalt), currentMaterial.algorithm.name, 'derive');
6318
6351
  if (setKey) {
6319
- this.setKeyFromMaterial(newMaterial, currentKeyIndex, true);
6352
+ yield this.setKeyFromMaterial(newMaterial, currentKeyIndex, true);
6320
6353
  this.emit(KeyHandlerEvent.KeyRatcheted, newMaterial, this.participantIdentity, currentKeyIndex);
6321
6354
  }
6322
6355
  resolve(newMaterial);
@@ -6341,7 +6374,7 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
6341
6374
  let keyIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
6342
6375
  return function* () {
6343
6376
  yield _this.setKeyFromMaterial(material, keyIndex);
6344
- _this.resetKeyStatus();
6377
+ _this.resetKeyStatus(keyIndex);
6345
6378
  }();
6346
6379
  });
6347
6380
  }
@@ -6378,7 +6411,7 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
6378
6411
  setCurrentKeyIndex(index) {
6379
6412
  return __awaiter(this, void 0, void 0, function* () {
6380
6413
  this.currentKeyIndex = index % this.cryptoKeyRing.length;
6381
- this.resetKeyStatus();
6414
+ this.resetKeyStatus(index);
6382
6415
  });
6383
6416
  }
6384
6417
  getCurrentKeyIndex() {