livekit-client 1.12.3 → 1.13.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) 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 +198 -107
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +515 -192
  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 +9 -3
  15. package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
  16. package/dist/src/e2ee/KeyProvider.d.ts +10 -7
  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/events.d.ts +34 -0
  21. package/dist/src/e2ee/events.d.ts.map +1 -0
  22. package/dist/src/e2ee/index.d.ts +1 -0
  23. package/dist/src/e2ee/index.d.ts.map +1 -1
  24. package/dist/src/e2ee/types.d.ts +23 -33
  25. package/dist/src/e2ee/types.d.ts.map +1 -1
  26. package/dist/src/e2ee/utils.d.ts +1 -0
  27. package/dist/src/e2ee/utils.d.ts.map +1 -1
  28. package/dist/src/e2ee/worker/FrameCryptor.d.ts +18 -13
  29. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  30. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts +6 -8
  31. package/dist/src/e2ee/worker/ParticipantKeyHandler.d.ts.map +1 -1
  32. package/dist/src/e2ee/worker/SifGuard.d.ts +11 -0
  33. package/dist/src/e2ee/worker/SifGuard.d.ts.map +1 -0
  34. package/dist/src/options.d.ts +5 -0
  35. package/dist/src/options.d.ts.map +1 -1
  36. package/dist/src/proto/livekit_models_pb.d.ts.map +1 -1
  37. package/dist/src/proto/livekit_rtc_pb.d.ts.map +1 -1
  38. package/dist/src/room/DeviceManager.d.ts +1 -0
  39. package/dist/src/room/DeviceManager.d.ts.map +1 -1
  40. package/dist/src/room/PCTransport.d.ts.map +1 -1
  41. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  42. package/dist/src/room/Room.d.ts +1 -1
  43. package/dist/src/room/Room.d.ts.map +1 -1
  44. package/dist/src/room/defaults.d.ts.map +1 -1
  45. package/dist/src/room/participant/LocalParticipant.d.ts +1 -0
  46. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  47. package/dist/src/room/participant/Participant.d.ts +5 -0
  48. package/dist/src/room/participant/Participant.d.ts.map +1 -1
  49. package/dist/src/room/participant/RemoteParticipant.d.ts +0 -5
  50. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  51. package/dist/src/room/timers.d.ts +2 -2
  52. package/dist/src/room/timers.d.ts.map +1 -1
  53. package/dist/src/room/track/LocalAudioTrack.d.ts +9 -1
  54. package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
  55. package/dist/src/room/track/LocalTrack.d.ts +3 -3
  56. package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
  57. package/dist/src/room/track/LocalVideoTrack.d.ts +6 -0
  58. package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
  59. package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
  60. package/dist/src/room/track/processor/types.d.ts +14 -2
  61. package/dist/src/room/track/processor/types.d.ts.map +1 -1
  62. package/dist/src/room/types.d.ts +1 -1
  63. package/dist/src/room/types.d.ts.map +1 -1
  64. package/dist/ts4.2/src/api/SignalClient.d.ts +2 -5
  65. package/dist/ts4.2/src/e2ee/E2eeManager.d.ts +9 -3
  66. package/dist/ts4.2/src/e2ee/KeyProvider.d.ts +10 -7
  67. package/dist/ts4.2/src/e2ee/constants.d.ts +2 -0
  68. package/dist/ts4.2/src/e2ee/events.d.ts +34 -0
  69. package/dist/ts4.2/src/e2ee/index.d.ts +1 -0
  70. package/dist/ts4.2/src/e2ee/types.d.ts +23 -33
  71. package/dist/ts4.2/src/e2ee/utils.d.ts +1 -0
  72. package/dist/ts4.2/src/e2ee/worker/FrameCryptor.d.ts +18 -13
  73. package/dist/ts4.2/src/e2ee/worker/ParticipantKeyHandler.d.ts +6 -8
  74. package/dist/ts4.2/src/e2ee/worker/SifGuard.d.ts +11 -0
  75. package/dist/ts4.2/src/options.d.ts +5 -0
  76. package/dist/ts4.2/src/room/DeviceManager.d.ts +1 -0
  77. package/dist/ts4.2/src/room/Room.d.ts +1 -1
  78. package/dist/ts4.2/src/room/participant/LocalParticipant.d.ts +1 -0
  79. package/dist/ts4.2/src/room/participant/Participant.d.ts +5 -0
  80. package/dist/ts4.2/src/room/participant/RemoteParticipant.d.ts +0 -5
  81. package/dist/ts4.2/src/room/timers.d.ts +2 -2
  82. package/dist/ts4.2/src/room/track/LocalAudioTrack.d.ts +9 -1
  83. package/dist/ts4.2/src/room/track/LocalTrack.d.ts +3 -3
  84. package/dist/ts4.2/src/room/track/LocalVideoTrack.d.ts +6 -0
  85. package/dist/ts4.2/src/room/track/processor/types.d.ts +14 -2
  86. package/dist/ts4.2/src/room/types.d.ts +1 -1
  87. package/package.json +15 -16
  88. package/src/api/SignalClient.ts +13 -9
  89. package/src/connectionHelper/checks/turn.ts +1 -0
  90. package/src/connectionHelper/checks/webrtc.ts +9 -7
  91. package/src/connectionHelper/checks/websocket.ts +1 -0
  92. package/src/e2ee/E2eeManager.ts +129 -76
  93. package/src/e2ee/KeyProvider.ts +31 -16
  94. package/src/e2ee/constants.ts +3 -0
  95. package/src/e2ee/events.ts +48 -0
  96. package/src/e2ee/index.ts +1 -0
  97. package/src/e2ee/types.ts +27 -41
  98. package/src/e2ee/utils.ts +9 -0
  99. package/src/e2ee/worker/FrameCryptor.ts +90 -47
  100. package/src/e2ee/worker/ParticipantKeyHandler.ts +25 -26
  101. package/src/e2ee/worker/SifGuard.ts +47 -0
  102. package/src/e2ee/worker/e2ee.worker.ts +75 -68
  103. package/src/options.ts +6 -0
  104. package/src/proto/livekit_models_pb.ts +14 -0
  105. package/src/proto/livekit_rtc_pb.ts +14 -0
  106. package/src/room/DeviceManager.ts +7 -2
  107. package/src/room/PCTransport.ts +12 -2
  108. package/src/room/RTCEngine.ts +3 -2
  109. package/src/room/Room.ts +47 -22
  110. package/src/room/defaults.ts +1 -0
  111. package/src/room/participant/LocalParticipant.ts +18 -2
  112. package/src/room/participant/Participant.ts +16 -0
  113. package/src/room/participant/RemoteParticipant.ts +0 -12
  114. package/src/room/track/LocalAudioTrack.ts +45 -0
  115. package/src/room/track/LocalTrack.ts +22 -14
  116. package/src/room/track/LocalVideoTrack.ts +39 -0
  117. package/src/room/track/RemoteAudioTrack.ts +9 -1
  118. package/src/room/track/RemoteTrackPublication.ts +2 -2
  119. package/src/room/track/facingMode.ts +1 -1
  120. package/src/room/track/processor/types.ts +18 -2
  121. 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) {
@@ -390,6 +392,26 @@ class CryptorError extends LivekitError {
390
392
  }
391
393
  }
392
394
 
395
+ var KeyProviderEvent;
396
+ (function (KeyProviderEvent) {
397
+ KeyProviderEvent["SetKey"] = "setKey";
398
+ KeyProviderEvent["RatchetRequest"] = "ratchetRequest";
399
+ KeyProviderEvent["KeyRatcheted"] = "keyRatcheted";
400
+ })(KeyProviderEvent || (KeyProviderEvent = {}));
401
+ var KeyHandlerEvent;
402
+ (function (KeyHandlerEvent) {
403
+ KeyHandlerEvent["KeyRatcheted"] = "keyRatcheted";
404
+ })(KeyHandlerEvent || (KeyHandlerEvent = {}));
405
+ var EncryptionEvent;
406
+ (function (EncryptionEvent) {
407
+ EncryptionEvent["ParticipantEncryptionStatusChanged"] = "participantEncryptionStatusChanged";
408
+ EncryptionEvent["EncryptionError"] = "encryptionError";
409
+ })(EncryptionEvent || (EncryptionEvent = {}));
410
+ var CryptorEvent;
411
+ (function (CryptorEvent) {
412
+ CryptorEvent["Error"] = "cryptorError";
413
+ })(CryptorEvent || (CryptorEvent = {}));
414
+
393
415
  var events = {exports: {}};
394
416
 
395
417
  var R = typeof Reflect === 'object' ? Reflect : null;
@@ -771,10 +793,6 @@ function eventTargetAgnosticAddListener(emitter, name, listener, flags) {
771
793
  }
772
794
  var eventsExports = events.exports;
773
795
 
774
- const CryptorEvent = {
775
- Error: 'cryptorError'
776
- };
777
-
778
796
  var AudioPresets;
779
797
  (function (AudioPresets) {
780
798
  AudioPresets.telephone = {
@@ -865,6 +883,43 @@ function ratchet(material, salt) {
865
883
  });
866
884
  }
867
885
 
886
+ class SifGuard {
887
+ constructor() {
888
+ this.consecutiveSifCount = 0;
889
+ this.lastSifReceivedAt = 0;
890
+ this.userFramesSinceSif = 0;
891
+ }
892
+ recordSif() {
893
+ var _a;
894
+ this.consecutiveSifCount += 1;
895
+ (_a = this.sifSequenceStartedAt) !== null && _a !== void 0 ? _a : this.sifSequenceStartedAt = Date.now();
896
+ this.lastSifReceivedAt = Date.now();
897
+ }
898
+ recordUserFrame() {
899
+ if (this.sifSequenceStartedAt === undefined) {
900
+ return;
901
+ } else {
902
+ this.userFramesSinceSif += 1;
903
+ }
904
+ if (
905
+ // reset if we received more user frames than SIFs
906
+ this.userFramesSinceSif > this.consecutiveSifCount ||
907
+ // also reset if we got a new user frame and the latest SIF frame hasn't been updated in a while
908
+ Date.now() - this.lastSifReceivedAt > MAX_SIF_DURATION) {
909
+ this.reset();
910
+ }
911
+ }
912
+ isSifAllowed() {
913
+ return this.consecutiveSifCount < MAX_SIF_COUNT && (this.sifSequenceStartedAt === undefined || Date.now() - this.sifSequenceStartedAt < MAX_SIF_DURATION);
914
+ }
915
+ reset() {
916
+ this.userFramesSinceSif = 0;
917
+ this.consecutiveSifCount = 0;
918
+ this.sifSequenceStartedAt = undefined;
919
+ }
920
+ }
921
+
922
+ const encryptionEnabledMap = new Map();
868
923
  class BaseFrameCryptor extends eventsExports.EventEmitter {
869
924
  encodeFunction(encodedFrame, controller) {
870
925
  throw Error('not implemented for subclass');
@@ -883,10 +938,11 @@ class FrameCryptor extends BaseFrameCryptor {
883
938
  super();
884
939
  this.sendCounts = new Map();
885
940
  this.keys = opts.keys;
886
- this.participantId = opts.participantId;
941
+ this.participantIdentity = opts.participantIdentity;
887
942
  this.rtpMap = new Map();
888
943
  this.keyProviderOptions = opts.keyProviderOptions;
889
- this.unencryptedFrameByteTrailer = (_a = opts.unencryptedFrameBytes) !== null && _a !== void 0 ? _a : new TextEncoder().encode('LKROCKS');
944
+ this.sifTrailer = (_a = opts.sifTrailer) !== null && _a !== void 0 ? _a : Uint8Array.from([]);
945
+ this.sifGuard = new SifGuard();
890
946
  }
891
947
  /**
892
948
  * Assign a different participant to the cryptor.
@@ -895,14 +951,22 @@ class FrameCryptor extends BaseFrameCryptor {
895
951
  * @param keys
896
952
  */
897
953
  setParticipant(id, keys) {
898
- this.participantId = id;
954
+ this.participantIdentity = id;
899
955
  this.keys = keys;
956
+ this.sifGuard.reset();
900
957
  }
901
958
  unsetParticipant() {
902
- this.participantId = undefined;
959
+ this.participantIdentity = undefined;
903
960
  }
904
- getParticipantId() {
905
- return this.participantId;
961
+ isEnabled() {
962
+ if (this.participantIdentity) {
963
+ return encryptionEnabledMap.get(this.participantIdentity);
964
+ } else {
965
+ return undefined;
966
+ }
967
+ }
968
+ getParticipantIdentity() {
969
+ return this.participantIdentity;
906
970
  }
907
971
  getTrackId() {
908
972
  return this.trackId;
@@ -923,7 +987,9 @@ class FrameCryptor extends BaseFrameCryptor {
923
987
  }
924
988
  setupTransform(operation, readable, writable, trackId, codec) {
925
989
  if (codec) {
926
- console.info('setting codec on cryptor to', codec);
990
+ workerLogger.info('setting codec on cryptor to', {
991
+ codec
992
+ });
927
993
  this.videoCodec = codec;
928
994
  }
929
995
  const transformFn = operation === 'encode' ? this.encodeFunction : this.decodeFunction;
@@ -931,11 +997,14 @@ class FrameCryptor extends BaseFrameCryptor {
931
997
  transform: transformFn.bind(this)
932
998
  });
933
999
  readable.pipeThrough(transformStream).pipeTo(writable).catch(e => {
934
- console.error(e);
935
- this.emit('cryptorError', e instanceof CryptorError ? e : new CryptorError(e.message));
1000
+ workerLogger.warn(e);
1001
+ this.emit(CryptorEvent.Error, e instanceof CryptorError ? e : new CryptorError(e.message));
936
1002
  });
937
1003
  this.trackId = trackId;
938
1004
  }
1005
+ setSifTrailer(trailer) {
1006
+ this.sifTrailer = trailer;
1007
+ }
939
1008
  /**
940
1009
  * Function that will be injected in a stream and will encrypt the given encoded frames.
941
1010
  *
@@ -961,14 +1030,18 @@ class FrameCryptor extends BaseFrameCryptor {
961
1030
  encodeFunction(encodedFrame, controller) {
962
1031
  var _a;
963
1032
  return __awaiter(this, void 0, void 0, function* () {
964
- if (!this.keys.isEnabled() ||
1033
+ if (!this.isEnabled() ||
965
1034
  // skip for encryption for empty dtx frames
966
1035
  encodedFrame.data.byteLength === 0) {
967
1036
  return controller.enqueue(encodedFrame);
968
1037
  }
1038
+ const keySet = this.keys.getKeySet();
1039
+ if (!keySet) {
1040
+ throw new TypeError("key set not found for ".concat(this.participantIdentity, " at index ").concat(this.keys.getCurrentKeyIndex()));
1041
+ }
969
1042
  const {
970
1043
  encryptionKey
971
- } = this.keys.getKeySet();
1044
+ } = keySet;
972
1045
  const keyIndex = this.keys.getCurrentKeyIndex();
973
1046
  if (encryptionKey) {
974
1047
  const iv = this.makeIV((_a = encodedFrame.getMetadata().synchronizationSource) !== null && _a !== void 0 ? _a : -1, encodedFrame.timestamp);
@@ -1016,13 +1089,23 @@ class FrameCryptor extends BaseFrameCryptor {
1016
1089
  */
1017
1090
  decodeFunction(encodedFrame, controller) {
1018
1091
  return __awaiter(this, void 0, void 0, function* () {
1019
- if (!this.keys.isEnabled() ||
1092
+ if (!this.isEnabled() ||
1020
1093
  // 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)) {
1094
+ encodedFrame.data.byteLength === 0) {
1095
+ this.sifGuard.recordUserFrame();
1024
1096
  return controller.enqueue(encodedFrame);
1025
1097
  }
1098
+ if (isFrameServerInjected(encodedFrame.data, this.sifTrailer)) {
1099
+ this.sifGuard.recordSif();
1100
+ if (this.sifGuard.isSifAllowed()) {
1101
+ return controller.enqueue(encodedFrame);
1102
+ } else {
1103
+ workerLogger.warn('SIF limit reached, dropping frame');
1104
+ return;
1105
+ }
1106
+ } else {
1107
+ this.sifGuard.recordUserFrame();
1108
+ }
1026
1109
  const data = new Uint8Array(encodedFrame.data);
1027
1110
  const keyIndex = data[encodedFrame.data.byteLength - 1];
1028
1111
  if (this.keys.getKeySet(keyIndex) && this.keys.hasValidKey) {
@@ -1035,8 +1118,7 @@ class FrameCryptor extends BaseFrameCryptor {
1035
1118
  } catch (error) {
1036
1119
  if (error instanceof CryptorError && error.reason === CryptorErrorReason.InvalidKey) {
1037
1120
  if (this.keys.hasValidKey) {
1038
- workerLogger.warn('invalid key');
1039
- this.emit(CryptorEvent.Error, new CryptorError("invalid key for participant ".concat(this.participantId), CryptorErrorReason.InvalidKey));
1121
+ this.emit(CryptorEvent.Error, new CryptorError("invalid key for participant ".concat(this.participantIdentity), CryptorErrorReason.InvalidKey));
1040
1122
  this.keys.decryptionFailure();
1041
1123
  }
1042
1124
  } else {
@@ -1045,8 +1127,11 @@ class FrameCryptor extends BaseFrameCryptor {
1045
1127
  });
1046
1128
  }
1047
1129
  }
1130
+ } else if (!this.keys.getKeySet(keyIndex) && this.keys.hasValidKey) {
1131
+ // emit an error in case the key index is out of bounds but the key handler thinks we still have a valid key
1132
+ workerLogger.warn('skipping decryption due to missing key at index');
1133
+ this.emit(CryptorEvent.Error, new CryptorError("missing key at index for participant ".concat(this.participantIdentity), CryptorErrorReason.MissingKey));
1048
1134
  }
1049
- return controller.enqueue(encodedFrame);
1050
1135
  });
1051
1136
  }
1052
1137
  /**
@@ -1061,6 +1146,9 @@ class FrameCryptor extends BaseFrameCryptor {
1061
1146
  var _a;
1062
1147
  return __awaiter(this, void 0, void 0, function* () {
1063
1148
  const keySet = this.keys.getKeySet(keyIndex);
1149
+ if (!ratchetOpts.encryptionKey && !keySet) {
1150
+ throw new TypeError("no encryption key found for decryption of ".concat(this.participantIdentity));
1151
+ }
1064
1152
  // Construct frame trailer. Similar to the frame header described in
1065
1153
  // https://tools.ietf.org/html/draft-omara-sframe-00#section-4.2
1066
1154
  // but we put it at the end.
@@ -1118,8 +1206,8 @@ class FrameCryptor extends BaseFrameCryptor {
1118
1206
  workerLogger.debug('resetting to initial material');
1119
1207
  this.keys.setKeyFromMaterial(initialMaterial.material, keyIndex);
1120
1208
  }
1121
- 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));
1209
+ workerLogger.warn('maximum ratchet attempts exceeded');
1210
+ throw new CryptorError("valid key missing for participant ".concat(this.participantIdentity), CryptorErrorReason.InvalidKey);
1123
1211
  }
1124
1212
  } else {
1125
1213
  throw new CryptorError('Decryption failed, most likely because of an invalid key', CryptorErrorReason.InvalidKey);
@@ -1291,6 +1379,9 @@ var NALUType;
1291
1379
  * @internal
1292
1380
  */
1293
1381
  function isFrameServerInjected(frameData, trailerBytes) {
1382
+ if (trailerBytes.byteLength === 0) {
1383
+ return false;
1384
+ }
1294
1385
  const frameTrailer = new Uint8Array(frameData.slice(frameData.byteLength - trailerBytes.byteLength));
1295
1386
  return trailerBytes.every((value, index) => value === frameTrailer[index]);
1296
1387
  }
@@ -1309,27 +1400,24 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1309
1400
  get hasValidKey() {
1310
1401
  return this._hasValidKey;
1311
1402
  }
1312
- constructor(participantId, isEnabled, keyProviderOptions) {
1403
+ constructor(participantIdentity, keyProviderOptions) {
1313
1404
  super();
1314
1405
  this.decryptionFailureCount = 0;
1315
1406
  this._hasValidKey = true;
1316
1407
  this.currentKeyIndex = 0;
1317
- this.cryptoKeyRing = new Array(KEYRING_SIZE);
1318
- this.enabled = isEnabled;
1408
+ this.cryptoKeyRing = new Array(KEYRING_SIZE).fill(undefined);
1319
1409
  this.keyProviderOptions = keyProviderOptions;
1320
1410
  this.ratchetPromiseMap = new Map();
1321
- this.participantId = participantId;
1411
+ this.participantIdentity = participantIdentity;
1322
1412
  this.resetKeyStatus();
1323
1413
  }
1324
- setEnabled(enabled) {
1325
- this.enabled = enabled;
1326
- }
1327
1414
  decryptionFailure() {
1328
1415
  if (this.keyProviderOptions.failureTolerance < 0) {
1329
1416
  return;
1330
1417
  }
1331
1418
  this.decryptionFailureCount += 1;
1332
1419
  if (this.decryptionFailureCount > this.keyProviderOptions.failureTolerance) {
1420
+ workerLogger.warn("key for ".concat(this.participantIdentity, " is being marked as invalid"));
1333
1421
  this._hasValidKey = false;
1334
1422
  }
1335
1423
  }
@@ -1353,19 +1441,23 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1353
1441
  */
1354
1442
  ratchetKey(keyIndex) {
1355
1443
  let setKey = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
1356
- const currentKeyIndex = keyIndex !== null && keyIndex !== void 0 ? keyIndex : keyIndex = this.getCurrentKeyIndex();
1444
+ const currentKeyIndex = keyIndex !== null && keyIndex !== void 0 ? keyIndex : this.getCurrentKeyIndex();
1357
1445
  const existingPromise = this.ratchetPromiseMap.get(currentKeyIndex);
1358
1446
  if (typeof existingPromise !== 'undefined') {
1359
1447
  return existingPromise;
1360
1448
  }
1361
1449
  const ratchetPromise = new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
1362
1450
  try {
1363
- const currentMaterial = this.getKeySet(currentKeyIndex).material;
1451
+ const keySet = this.getKeySet(currentKeyIndex);
1452
+ if (!keySet) {
1453
+ throw new TypeError("Cannot ratchet key without a valid keyset of participant ".concat(this.participantIdentity));
1454
+ }
1455
+ const currentMaterial = keySet.material;
1364
1456
  const newMaterial = yield importKey(yield ratchet(currentMaterial, this.keyProviderOptions.ratchetSalt), currentMaterial.algorithm.name, 'derive');
1365
1457
  if (setKey) {
1366
1458
  this.setKeyFromMaterial(newMaterial, currentKeyIndex, true);
1459
+ this.emit(KeyHandlerEvent.KeyRatcheted, newMaterial, this.participantIdentity, currentKeyIndex);
1367
1460
  }
1368
- this.emit('keyRatcheted', newMaterial, keyIndex, this.participantId);
1369
1461
  resolve(newMaterial);
1370
1462
  } catch (e) {
1371
1463
  reject(e);
@@ -1409,12 +1501,10 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1409
1501
  }
1410
1502
  setKeySet(keySet, keyIndex) {
1411
1503
  let emitRatchetEvent = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
1412
- return __awaiter(this, void 0, void 0, function* () {
1413
- this.cryptoKeyRing[keyIndex % this.cryptoKeyRing.length] = keySet;
1414
- if (emitRatchetEvent) {
1415
- this.emit('keyRatcheted', keySet.material, keyIndex, this.participantId);
1416
- }
1417
- });
1504
+ this.cryptoKeyRing[keyIndex % this.cryptoKeyRing.length] = keySet;
1505
+ if (emitRatchetEvent) {
1506
+ this.emit(KeyHandlerEvent.KeyRatcheted, keySet.material, this.participantIdentity, keyIndex);
1507
+ }
1418
1508
  }
1419
1509
  setCurrentKeyIndex(index) {
1420
1510
  return __awaiter(this, void 0, void 0, function* () {
@@ -1422,9 +1512,6 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1422
1512
  this.resetKeyStatus();
1423
1513
  });
1424
1514
  }
1425
- isEnabled() {
1426
- return this.enabled;
1427
- }
1428
1515
  getCurrentKeyIndex() {
1429
1516
  return this.currentKeyIndex;
1430
1517
  }
@@ -1440,11 +1527,11 @@ class ParticipantKeyHandler extends eventsExports.EventEmitter {
1440
1527
 
1441
1528
  const participantCryptors = [];
1442
1529
  const participantKeys = new Map();
1443
- let publishCryptors = [];
1444
- let publisherKeys;
1530
+ let sharedKeyHandler;
1445
1531
  let isEncryptionEnabled = false;
1446
1532
  let useSharedKey = false;
1447
1533
  let sharedKey;
1534
+ let sifTrailer;
1448
1535
  let keyProviderOptions = KEY_PROVIDER_DEFAULTS;
1449
1536
  workerLogger.setDefaultLevel('info');
1450
1537
  onmessage = ev => {
@@ -1458,36 +1545,35 @@ onmessage = ev => {
1458
1545
  keyProviderOptions = data.keyProviderOptions;
1459
1546
  useSharedKey = !!data.keyProviderOptions.sharedKey;
1460
1547
  // acknowledge init successful
1461
- const enableMsg = {
1462
- kind: 'enable',
1548
+ const ackMsg = {
1549
+ kind: 'initAck',
1463
1550
  data: {
1464
1551
  enabled: isEncryptionEnabled
1465
1552
  }
1466
1553
  };
1467
- publisherKeys = new ParticipantKeyHandler(undefined, isEncryptionEnabled, keyProviderOptions);
1468
- publisherKeys.on('keyRatcheted', emitRatchetedKeys);
1469
- postMessage(enableMsg);
1554
+ postMessage(ackMsg);
1470
1555
  break;
1471
1556
  case 'enable':
1472
- setEncryptionEnabled(data.enabled, data.participantId);
1557
+ setEncryptionEnabled(data.enabled, data.participantIdentity);
1473
1558
  workerLogger.info('updated e2ee enabled status');
1474
1559
  // acknowledge enable call successful
1475
1560
  postMessage(ev.data);
1476
1561
  break;
1477
1562
  case 'decode':
1478
- let cryptor = getTrackCryptor(data.participantId, data.trackId);
1563
+ let cryptor = getTrackCryptor(data.participantIdentity, data.trackId);
1479
1564
  cryptor.setupTransform(kind, data.readableStream, data.writableStream, data.trackId, data.codec);
1480
1565
  break;
1481
1566
  case 'encode':
1482
- let pubCryptor = getPublisherCryptor(data.trackId);
1567
+ let pubCryptor = getTrackCryptor(data.participantIdentity, data.trackId);
1483
1568
  pubCryptor.setupTransform(kind, data.readableStream, data.writableStream, data.trackId, data.codec);
1484
1569
  break;
1485
1570
  case 'setKey':
1486
1571
  if (useSharedKey) {
1487
- workerLogger.debug('set shared key');
1572
+ workerLogger.warn('set shared key');
1488
1573
  setSharedKey(data.key, data.keyIndex);
1489
- } else if (data.participantId) {
1490
- getParticipantKeyHandler(data.participantId).setKey(data.key, data.keyIndex);
1574
+ } else if (data.participantIdentity) {
1575
+ workerLogger.warn("set participant sender key ".concat(data.participantIdentity));
1576
+ getParticipantKeyHandler(data.participantIdentity).setKey(data.key, data.keyIndex);
1491
1577
  } else {
1492
1578
  workerLogger.error('no participant Id was provided and shared key usage is disabled');
1493
1579
  }
@@ -1496,98 +1582,97 @@ onmessage = ev => {
1496
1582
  unsetCryptorParticipant(data.trackId);
1497
1583
  break;
1498
1584
  case 'updateCodec':
1499
- getTrackCryptor(data.participantId, data.trackId).setVideoCodec(data.codec);
1585
+ getTrackCryptor(data.participantIdentity, data.trackId).setVideoCodec(data.codec);
1500
1586
  break;
1501
1587
  case 'setRTPMap':
1502
- publishCryptors.forEach(cr => {
1503
- cr.setRtpMap(data.map);
1588
+ // this is only used for the local participant
1589
+ participantCryptors.forEach(cr => {
1590
+ if (cr.getParticipantIdentity() === data.participantIdentity) {
1591
+ cr.setRtpMap(data.map);
1592
+ }
1504
1593
  });
1505
1594
  break;
1506
1595
  case 'ratchetRequest':
1507
1596
  handleRatchetRequest(data);
1597
+ break;
1598
+ case 'setSifTrailer':
1599
+ handleSifTrailer(data.trailer);
1600
+ break;
1508
1601
  }
1509
1602
  };
1510
1603
  function handleRatchetRequest(data) {
1511
1604
  return __awaiter(this, void 0, void 0, function* () {
1512
- const keyHandler = getParticipantKeyHandler(data.participantId);
1513
- yield keyHandler.ratchetKey(data.keyIndex);
1514
- keyHandler.resetKeyStatus();
1605
+ if (useSharedKey) {
1606
+ const keyHandler = getSharedKeyHandler();
1607
+ yield keyHandler.ratchetKey(data.keyIndex);
1608
+ keyHandler.resetKeyStatus();
1609
+ } else if (data.participantIdentity) {
1610
+ const keyHandler = getParticipantKeyHandler(data.participantIdentity);
1611
+ yield keyHandler.ratchetKey(data.keyIndex);
1612
+ keyHandler.resetKeyStatus();
1613
+ } else {
1614
+ workerLogger.error('no participant Id was provided for ratchet request and shared key usage is disabled');
1615
+ }
1515
1616
  });
1516
1617
  }
1517
- function getTrackCryptor(participantId, trackId) {
1618
+ function getTrackCryptor(participantIdentity, trackId) {
1518
1619
  let cryptor = participantCryptors.find(c => c.getTrackId() === trackId);
1519
1620
  if (!cryptor) {
1520
1621
  workerLogger.info('creating new cryptor for', {
1521
- participantId
1622
+ participantIdentity
1522
1623
  });
1523
1624
  if (!keyProviderOptions) {
1524
1625
  throw Error('Missing keyProvider options');
1525
1626
  }
1526
1627
  cryptor = new FrameCryptor({
1527
- participantId,
1528
- keys: getParticipantKeyHandler(participantId),
1529
- keyProviderOptions
1628
+ participantIdentity,
1629
+ keys: getParticipantKeyHandler(participantIdentity),
1630
+ keyProviderOptions,
1631
+ sifTrailer
1530
1632
  });
1531
1633
  setupCryptorErrorEvents(cryptor);
1532
1634
  participantCryptors.push(cryptor);
1533
- } else if (participantId !== cryptor.getParticipantId()) {
1635
+ } else if (participantIdentity !== cryptor.getParticipantIdentity()) {
1534
1636
  // assign new participant id to track cryptor and pass in correct key handler
1535
- cryptor.setParticipant(participantId, getParticipantKeyHandler(participantId));
1637
+ cryptor.setParticipant(participantIdentity, getParticipantKeyHandler(participantIdentity));
1536
1638
  }
1537
1639
  return cryptor;
1538
1640
  }
1539
- function getParticipantKeyHandler(participantId) {
1540
- if (!participantId) {
1541
- return publisherKeys;
1641
+ function getParticipantKeyHandler(participantIdentity) {
1642
+ if (useSharedKey) {
1643
+ return getSharedKeyHandler();
1542
1644
  }
1543
- let keys = participantKeys.get(participantId);
1645
+ let keys = participantKeys.get(participantIdentity);
1544
1646
  if (!keys) {
1545
- keys = new ParticipantKeyHandler(participantId, true, keyProviderOptions);
1647
+ keys = new ParticipantKeyHandler(participantIdentity, keyProviderOptions);
1546
1648
  if (sharedKey) {
1547
1649
  keys.setKey(sharedKey);
1548
1650
  }
1549
- participantKeys.set(participantId, keys);
1651
+ keys.on(KeyHandlerEvent.KeyRatcheted, emitRatchetedKeys);
1652
+ participantKeys.set(participantIdentity, keys);
1550
1653
  }
1551
1654
  return keys;
1552
1655
  }
1656
+ function getSharedKeyHandler() {
1657
+ if (!sharedKeyHandler) {
1658
+ sharedKeyHandler = new ParticipantKeyHandler('shared-key', keyProviderOptions);
1659
+ }
1660
+ return sharedKeyHandler;
1661
+ }
1553
1662
  function unsetCryptorParticipant(trackId) {
1554
1663
  var _a;
1555
1664
  (_a = participantCryptors.find(c => c.getTrackId() === trackId)) === null || _a === void 0 ? void 0 : _a.unsetParticipant();
1556
1665
  }
1557
- function getPublisherCryptor(trackId) {
1558
- let publishCryptor = publishCryptors.find(cryptor => cryptor.getTrackId() === trackId);
1559
- if (!publishCryptor) {
1560
- if (!keyProviderOptions) {
1561
- throw new TypeError('Missing keyProvider options');
1562
- }
1563
- publishCryptor = new FrameCryptor({
1564
- keys: publisherKeys,
1565
- participantId: 'publisher',
1566
- keyProviderOptions
1567
- });
1568
- setupCryptorErrorEvents(publishCryptor);
1569
- publishCryptors.push(publishCryptor);
1570
- }
1571
- return publishCryptor;
1572
- }
1573
- function setEncryptionEnabled(enable, participantId) {
1574
- if (!participantId) {
1575
- isEncryptionEnabled = enable;
1576
- publisherKeys.setEnabled(enable);
1577
- } else {
1578
- getParticipantKeyHandler(participantId).setEnabled(enable);
1579
- }
1666
+ function setEncryptionEnabled(enable, participantIdentity) {
1667
+ encryptionEnabledMap.set(participantIdentity, enable);
1580
1668
  }
1581
1669
  function setSharedKey(key, index) {
1582
1670
  workerLogger.debug('setting shared key');
1583
1671
  sharedKey = key;
1584
- publisherKeys === null || publisherKeys === void 0 ? void 0 : publisherKeys.setKey(key, index);
1585
- for (const [, keyHandler] of participantKeys) {
1586
- keyHandler.setKey(key, index);
1587
- }
1672
+ getSharedKeyHandler().setKey(key, index);
1588
1673
  }
1589
1674
  function setupCryptorErrorEvents(cryptor) {
1590
- cryptor.on('cryptorError', error => {
1675
+ cryptor.on(CryptorEvent.Error, error => {
1591
1676
  const msg = {
1592
1677
  kind: 'error',
1593
1678
  data: {
@@ -1597,17 +1682,23 @@ function setupCryptorErrorEvents(cryptor) {
1597
1682
  postMessage(msg);
1598
1683
  });
1599
1684
  }
1600
- function emitRatchetedKeys(material, keyIndex) {
1685
+ function emitRatchetedKeys(material, participantIdentity, keyIndex) {
1601
1686
  const msg = {
1602
1687
  kind: "ratchetKey",
1603
1688
  data: {
1604
- // participantId,
1689
+ participantIdentity,
1605
1690
  keyIndex,
1606
1691
  material
1607
1692
  }
1608
1693
  };
1609
1694
  postMessage(msg);
1610
1695
  }
1696
+ function handleSifTrailer(trailer) {
1697
+ sifTrailer = trailer;
1698
+ participantCryptors.forEach(c => {
1699
+ c.setSifTrailer(trailer);
1700
+ });
1701
+ }
1611
1702
  // Operations using RTCRtpScriptTransform.
1612
1703
  // @ts-ignore
1613
1704
  if (self.RTCTransformEvent) {
@@ -1619,11 +1710,11 @@ if (self.RTCTransformEvent) {
1619
1710
  transformer.handled = true;
1620
1711
  const {
1621
1712
  kind,
1622
- participantId,
1713
+ participantIdentity,
1623
1714
  trackId,
1624
1715
  codec
1625
1716
  } = transformer.options;
1626
- const cryptor = kind === 'encode' ? getPublisherCryptor(trackId) : getTrackCryptor(participantId, trackId);
1717
+ const cryptor = getTrackCryptor(participantIdentity, trackId);
1627
1718
  workerLogger.debug('transform', {
1628
1719
  codec
1629
1720
  });