livekit-client 2.5.7 → 2.5.9

Sign up to get free protection for your applications and to get access to all the features.
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() {