livekit-client 1.12.2 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) 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 +83 -9
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +2239 -1975
  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 -5
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/connectionHelper/checks/turn.d.ts.map +1 -1
  12. package/dist/src/connectionHelper/checks/webrtc.d.ts.map +1 -1
  13. package/dist/src/connectionHelper/checks/websocket.d.ts.map +1 -1
  14. package/dist/src/e2ee/E2eeManager.d.ts +5 -0
  15. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  16. package/dist/src/e2ee/KeyProvider.d.ts +4 -2
  17. package/dist/src/e2ee/KeyProvider.d.ts.map +1 -1
  18. package/dist/src/e2ee/constants.d.ts +2 -0
  19. package/dist/src/e2ee/constants.d.ts.map +1 -1
  20. package/dist/src/e2ee/types.d.ts +7 -1
  21. package/dist/src/e2ee/types.d.ts.map +1 -1
  22. package/dist/src/e2ee/utils.d.ts +1 -0
  23. package/dist/src/e2ee/utils.d.ts.map +1 -1
  24. package/dist/src/e2ee/worker/FrameCryptor.d.ts +4 -2
  25. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  26. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts.map +1 -1
  27. package/dist/src/e2ee/worker/SifGuard.d.ts +11 -0
  28. package/dist/src/e2ee/worker/SifGuard.d.ts.map +1 -0
  29. package/dist/src/options.d.ts +5 -0
  30. package/dist/src/options.d.ts.map +1 -1
  31. package/dist/src/proto/livekit_models_pb.d.ts.map +1 -1
  32. package/dist/src/proto/livekit_rtc_pb.d.ts.map +1 -1
  33. package/dist/src/room/DeviceManager.d.ts +1 -0
  34. package/dist/src/room/DeviceManager.d.ts.map +1 -1
  35. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  36. package/dist/src/room/Room.d.ts +1 -1
  37. package/dist/src/room/Room.d.ts.map +1 -1
  38. package/dist/src/room/defaults.d.ts.map +1 -1
  39. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  40. package/dist/src/room/participant/Participant.d.ts +5 -0
  41. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  42. package/dist/src/room/participant/RemoteParticipant.d.ts +0 -5
  43. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  44. package/dist/src/room/participant/publishUtils.d.ts +1 -1
  45. package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
  46. package/dist/src/room/timers.d.ts +2 -2
  47. package/dist/src/room/timers.d.ts.map +1 -1
  48. package/dist/src/room/track/LocalAudioTrack.d.ts +9 -1
  49. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  50. package/dist/src/room/track/LocalTrack.d.ts +3 -3
  51. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  52. package/dist/src/room/track/LocalVideoTrack.d.ts +6 -0
  53. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  54. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
  55. package/dist/src/room/track/options.d.ts +1 -0
  56. package/dist/src/room/track/options.d.ts.map +1 -1
  57. package/dist/src/room/track/processor/types.d.ts +13 -2
  58. package/dist/src/room/track/processor/types.d.ts.map +1 -1
  59. package/dist/src/room/types.d.ts +1 -1
  60. package/dist/src/room/types.d.ts.map +1 -1
  61. package/dist/ts4.2/src/api/SignalClient.d.ts +2 -5
  62. package/dist/ts4.2/src/e2ee/E2eeManager.d.ts +5 -0
  63. package/dist/ts4.2/src/e2ee/KeyProvider.d.ts +4 -2
  64. package/dist/ts4.2/src/e2ee/constants.d.ts +2 -0
  65. package/dist/ts4.2/src/e2ee/types.d.ts +7 -1
  66. package/dist/ts4.2/src/e2ee/utils.d.ts +1 -0
  67. package/dist/ts4.2/src/e2ee/worker/FrameCryptor.d.ts +4 -2
  68. package/dist/ts4.2/src/e2ee/worker/SifGuard.d.ts +11 -0
  69. package/dist/ts4.2/src/options.d.ts +5 -0
  70. package/dist/ts4.2/src/room/DeviceManager.d.ts +1 -0
  71. package/dist/ts4.2/src/room/Room.d.ts +1 -1
  72. package/dist/ts4.2/src/room/participant/Participant.d.ts +5 -0
  73. package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +0 -5
  74. package/dist/ts4.2/src/room/participant/publishUtils.d.ts +1 -1
  75. package/dist/ts4.2/src/room/timers.d.ts +2 -2
  76. package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +9 -1
  77. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -3
  78. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +6 -0
  79. package/dist/ts4.2/src/room/track/options.d.ts +1 -0
  80. package/dist/ts4.2/src/room/track/processor/types.d.ts +13 -2
  81. package/dist/ts4.2/src/room/types.d.ts +1 -1
  82. package/package.json +15 -16
  83. package/src/api/SignalClient.ts +13 -9
  84. package/src/connectionHelper/checks/turn.ts +1 -0
  85. package/src/connectionHelper/checks/webrtc.ts +9 -7
  86. package/src/connectionHelper/checks/websocket.ts +1 -0
  87. package/src/e2ee/E2eeManager.ts +27 -2
  88. package/src/e2ee/KeyProvider.ts +9 -4
  89. package/src/e2ee/constants.ts +3 -0
  90. package/src/e2ee/types.ts +9 -1
  91. package/src/e2ee/utils.ts +9 -0
  92. package/src/e2ee/worker/FrameCryptor.ts +46 -17
  93. package/src/e2ee/worker/ParticipantKeyHandler.ts +1 -0
  94. package/src/e2ee/worker/SifGuard.ts +47 -0
  95. package/src/e2ee/worker/e2ee.worker.ts +14 -0
  96. package/src/options.ts +6 -0
  97. package/src/proto/livekit_models_pb.ts +14 -0
  98. package/src/proto/livekit_rtc_pb.ts +14 -0
  99. package/src/room/DeviceManager.ts +7 -2
  100. package/src/room/RTCEngine.ts +7 -5
  101. package/src/room/Room.ts +27 -7
  102. package/src/room/defaults.ts +1 -0
  103. package/src/room/participant/LocalParticipant.ts +14 -2
  104. package/src/room/participant/Participant.ts +16 -0
  105. package/src/room/participant/RemoteParticipant.ts +0 -12
  106. package/src/room/participant/publishUtils.ts +4 -2
  107. package/src/room/track/LocalAudioTrack.ts +45 -0
  108. package/src/room/track/LocalTrack.ts +4 -4
  109. package/src/room/track/LocalVideoTrack.ts +49 -8
  110. package/src/room/track/RemoteAudioTrack.ts +9 -1
  111. package/src/room/track/RemoteTrackPublication.ts +2 -2
  112. package/src/room/track/options.ts +17 -16
  113. package/src/room/track/processor/types.ts +17 -2
  114. package/src/room/types.ts +5 -1
@@ -341,6 +341,8 @@ const KEY_PROVIDER_DEFAULTS = {
341
341
  ratchetWindowSize: 8,
342
342
  failureTolerance: DECRYPTION_FAILURE_TOLERANCE
343
343
  };
344
+ const MAX_SIF_COUNT = 100;
345
+ const MAX_SIF_DURATION = 2000;
344
346
 
345
347
  class LivekitError extends Error {
346
348
  constructor(code, message) {
@@ -865,6 +867,42 @@ function ratchet(material, salt) {
865
867
  });
866
868
  }
867
869
 
870
+ class SifGuard {
871
+ constructor() {
872
+ this.consecutiveSifCount = 0;
873
+ this.lastSifReceivedAt = 0;
874
+ this.userFramesSinceSif = 0;
875
+ }
876
+ recordSif() {
877
+ var _a;
878
+ this.consecutiveSifCount += 1;
879
+ (_a = this.sifSequenceStartedAt) !== null && _a !== void 0 ? _a : this.sifSequenceStartedAt = Date.now();
880
+ this.lastSifReceivedAt = Date.now();
881
+ }
882
+ recordUserFrame() {
883
+ if (this.sifSequenceStartedAt === undefined) {
884
+ return;
885
+ } else {
886
+ this.userFramesSinceSif += 1;
887
+ }
888
+ if (
889
+ // reset if we received more user frames than SIFs
890
+ this.userFramesSinceSif > this.consecutiveSifCount ||
891
+ // also reset if we got a new user frame and the latest SIF frame hasn't been updated in a while
892
+ Date.now() - this.lastSifReceivedAt > MAX_SIF_DURATION) {
893
+ this.reset();
894
+ }
895
+ }
896
+ isSifAllowed() {
897
+ return this.consecutiveSifCount < MAX_SIF_COUNT && (this.sifSequenceStartedAt === undefined || Date.now() - this.sifSequenceStartedAt < MAX_SIF_DURATION);
898
+ }
899
+ reset() {
900
+ this.userFramesSinceSif = 0;
901
+ this.consecutiveSifCount = 0;
902
+ this.sifSequenceStartedAt = undefined;
903
+ }
904
+ }
905
+
868
906
  class BaseFrameCryptor extends eventsExports.EventEmitter {
869
907
  encodeFunction(encodedFrame, controller) {
870
908
  throw Error('not implemented for subclass');
@@ -886,7 +924,8 @@ class FrameCryptor extends BaseFrameCryptor {
886
924
  this.participantId = opts.participantId;
887
925
  this.rtpMap = new Map();
888
926
  this.keyProviderOptions = opts.keyProviderOptions;
889
- this.unencryptedFrameByteTrailer = (_a = opts.unencryptedFrameBytes) !== null && _a !== void 0 ? _a : new TextEncoder().encode('LKROCKS');
927
+ this.sifTrailer = (_a = opts.sifTrailer) !== null && _a !== void 0 ? _a : Uint8Array.from([]);
928
+ this.sifGuard = new SifGuard();
890
929
  }
891
930
  /**
892
931
  * Assign a different participant to the cryptor.
@@ -897,6 +936,7 @@ class FrameCryptor extends BaseFrameCryptor {
897
936
  setParticipant(id, keys) {
898
937
  this.participantId = id;
899
938
  this.keys = keys;
939
+ this.sifGuard.reset();
900
940
  }
901
941
  unsetParticipant() {
902
942
  this.participantId = undefined;
@@ -923,7 +963,9 @@ class FrameCryptor extends BaseFrameCryptor {
923
963
  }
924
964
  setupTransform(operation, readable, writable, trackId, codec) {
925
965
  if (codec) {
926
- console.info('setting codec on cryptor to', codec);
966
+ workerLogger.info('setting codec on cryptor to', {
967
+ codec
968
+ });
927
969
  this.videoCodec = codec;
928
970
  }
929
971
  const transformFn = operation === 'encode' ? this.encodeFunction : this.decodeFunction;
@@ -931,7 +973,7 @@ class FrameCryptor extends BaseFrameCryptor {
931
973
  transform: transformFn.bind(this)
932
974
  });
933
975
  readable.pipeThrough(transformStream).pipeTo(writable).catch(e => {
934
- console.error(e);
976
+ workerLogger.warn(e);
935
977
  this.emit('cryptorError', e instanceof CryptorError ? e : new CryptorError(e.message));
936
978
  });
937
979
  this.trackId = trackId;
@@ -1018,11 +1060,21 @@ class FrameCryptor extends BaseFrameCryptor {
1018
1060
  return __awaiter(this, void 0, void 0, function* () {
1019
1061
  if (!this.keys.isEnabled() ||
1020
1062
  // skip for decryption for empty dtx frames
1021
- encodedFrame.data.byteLength === 0 ||
1022
- // skip decryption if frame is server injected
1023
- isFrameServerInjected(encodedFrame.data, this.unencryptedFrameByteTrailer)) {
1063
+ encodedFrame.data.byteLength === 0) {
1064
+ this.sifGuard.recordUserFrame();
1024
1065
  return controller.enqueue(encodedFrame);
1025
1066
  }
1067
+ if (isFrameServerInjected(encodedFrame.data, this.sifTrailer)) {
1068
+ this.sifGuard.recordSif();
1069
+ if (this.sifGuard.isSifAllowed()) {
1070
+ return controller.enqueue(encodedFrame);
1071
+ } else {
1072
+ workerLogger.warn('SIF limit reached, dropping frame');
1073
+ return;
1074
+ }
1075
+ } else {
1076
+ this.sifGuard.recordUserFrame();
1077
+ }
1026
1078
  const data = new Uint8Array(encodedFrame.data);
1027
1079
  const keyIndex = data[encodedFrame.data.byteLength - 1];
1028
1080
  if (this.keys.getKeySet(keyIndex) && this.keys.hasValidKey) {
@@ -1045,8 +1097,11 @@ class FrameCryptor extends BaseFrameCryptor {
1045
1097
  });
1046
1098
  }
1047
1099
  }
1100
+ } else if (!this.keys.getKeySet(keyIndex) && this.keys.hasValidKey) {
1101
+ // emit an error in case the key index is out of bounds but the key handler thinks we still have a valid key
1102
+ workerLogger.warn('skipping decryption due to missing key at index');
1103
+ this.emit(CryptorEvent.Error, new CryptorError("missing key at index for participant ".concat(this.participantId), CryptorErrorReason.MissingKey));
1048
1104
  }
1049
- return controller.enqueue(encodedFrame);
1050
1105
  });
1051
1106
  }
1052
1107
  /**
@@ -1119,7 +1174,7 @@ class FrameCryptor extends BaseFrameCryptor {
1119
1174
  this.keys.setKeyFromMaterial(initialMaterial.material, keyIndex);
1120
1175
  }
1121
1176
  workerLogger.warn('maximum ratchet attempts exceeded, resetting key');
1122
- this.emit(CryptorEvent.Error, new CryptorError("valid key missing for participant ".concat(this.participantId), CryptorErrorReason.MissingKey));
1177
+ throw new CryptorError("valid key missing for participant ".concat(this.participantId), CryptorErrorReason.InvalidKey);
1123
1178
  }
1124
1179
  } else {
1125
1180
  throw new CryptorError('Decryption failed, most likely because of an invalid key', CryptorErrorReason.InvalidKey);
@@ -1210,6 +1265,9 @@ class FrameCryptor extends BaseFrameCryptor {
1210
1265
  const codec = payloadType ? this.rtpMap.get(payloadType) : undefined;
1211
1266
  return codec;
1212
1267
  }
1268
+ setSifTrailer(trailer) {
1269
+ this.sifTrailer = trailer;
1270
+ }
1213
1271
  }
1214
1272
  /**
1215
1273
  * Slice the NALUs present in the supplied buffer, assuming it is already byte-aligned
@@ -1291,6 +1349,9 @@ var NALUType;
1291
1349
  * @internal
1292
1350
  */
1293
1351
  function isFrameServerInjected(frameData, trailerBytes) {
1352
+ if (trailerBytes.byteLength === 0) {
1353
+ return false;
1354
+ }
1294
1355
  const frameTrailer = new Uint8Array(frameData.slice(frameData.byteLength - trailerBytes.byteLength));
1295
1356
  return trailerBytes.every((value, index) => value === frameTrailer[index]);
1296
1357
  }
@@ -1330,6 +1391,7 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1330
1391
  }
1331
1392
  this.decryptionFailureCount += 1;
1332
1393
  if (this.decryptionFailureCount > this.keyProviderOptions.failureTolerance) {
1394
+ workerLogger.warn("key for ".concat(this.participantId, " is being marked as invalid"));
1333
1395
  this._hasValidKey = false;
1334
1396
  }
1335
1397
  }
@@ -1445,6 +1507,7 @@ let publisherKeys;
1445
1507
  let isEncryptionEnabled = false;
1446
1508
  let useSharedKey = false;
1447
1509
  let sharedKey;
1510
+ let sifTrailer;
1448
1511
  let keyProviderOptions = KEY_PROVIDER_DEFAULTS;
1449
1512
  workerLogger.setDefaultLevel('info');
1450
1513
  onmessage = ev => {
@@ -1505,6 +1568,10 @@ onmessage = ev => {
1505
1568
  break;
1506
1569
  case 'ratchetRequest':
1507
1570
  handleRatchetRequest(data);
1571
+ break;
1572
+ case 'setSifTrailer':
1573
+ handleSifTrailer(data.trailer);
1574
+ break;
1508
1575
  }
1509
1576
  };
1510
1577
  function handleRatchetRequest(data) {
@@ -1526,7 +1593,8 @@ function getTrackCryptor(participantId, trackId) {
1526
1593
  cryptor = new FrameCryptor({
1527
1594
  participantId,
1528
1595
  keys: getParticipantKeyHandler(participantId),
1529
- keyProviderOptions
1596
+ keyProviderOptions,
1597
+ sifTrailer
1530
1598
  });
1531
1599
  setupCryptorErrorEvents(cryptor);
1532
1600
  participantCryptors.push(cryptor);
@@ -1608,6 +1676,12 @@ function emitRatchetedKeys(material, keyIndex) {
1608
1676
  };
1609
1677
  postMessage(msg);
1610
1678
  }
1679
+ function handleSifTrailer(trailer) {
1680
+ sifTrailer = trailer;
1681
+ participantCryptors.forEach(c => {
1682
+ c.setSifTrailer(trailer);
1683
+ });
1684
+ }
1611
1685
  // Operations using RTCRtpScriptTransform.
1612
1686
  // @ts-ignore
1613
1687
  if (self.RTCTransformEvent) {