You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Worker.js 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /* global TransformStream */
  2. /* eslint-disable no-bitwise */
  3. // Worker for E2EE/Insertable streams.
  4. import { Context } from './Context';
  5. const contexts = new Map(); // Map participant id => context
  6. let sharedContext;
  7. /**
  8. * Retrieves the participant {@code Context}, creating it if necessary.
  9. *
  10. * @param {string} participantId - The participant whose context we need.
  11. * @returns {Object} The context.
  12. */
  13. function getParticipantContext(participantId) {
  14. if (sharedContext) {
  15. return sharedContext;
  16. }
  17. if (!contexts.has(participantId)) {
  18. contexts.set(participantId, new Context());
  19. }
  20. return contexts.get(participantId);
  21. }
  22. /**
  23. * Sets an encode / decode transform.
  24. *
  25. * @param {Object} context - The participant context where the transform will be applied.
  26. * @param {string} operation - Encode / decode.
  27. * @param {Object} readableStream - Readable stream part.
  28. * @param {Object} writableStream - Writable stream part.
  29. */
  30. function handleTransform(context, operation, readableStream, writableStream) {
  31. if (operation === 'encode' || operation === 'decode') {
  32. const transformFn = operation === 'encode' ? context.encodeFunction : context.decodeFunction;
  33. const transformStream = new TransformStream({
  34. transform: transformFn.bind(context)
  35. });
  36. readableStream
  37. .pipeThrough(transformStream)
  38. .pipeTo(writableStream);
  39. } else {
  40. console.error(`Invalid operation: ${operation}`);
  41. }
  42. }
  43. onmessage = async event => {
  44. const { operation } = event.data;
  45. if (operation === 'initialize') {
  46. const { sharedKey } = event.data;
  47. if (sharedKey) {
  48. sharedContext = new Context({ sharedKey });
  49. }
  50. } else if (operation === 'encode' || operation === 'decode') {
  51. const { readableStream, writableStream, participantId } = event.data;
  52. const context = getParticipantContext(participantId);
  53. handleTransform(context, operation, readableStream, writableStream);
  54. } else if (operation === 'setKey') {
  55. const { participantId, key, keyIndex } = event.data;
  56. const context = getParticipantContext(participantId);
  57. if (key) {
  58. context.setKey(key, keyIndex);
  59. } else {
  60. context.setKey(false, keyIndex);
  61. }
  62. } else if (operation === 'cleanup') {
  63. const { participantId } = event.data;
  64. contexts.delete(participantId);
  65. } else if (operation === 'cleanupAll') {
  66. contexts.clear();
  67. } else {
  68. console.error('e2ee worker', operation);
  69. }
  70. };
  71. // Operations using RTCRtpScriptTransform.
  72. if (self.RTCTransformEvent) {
  73. self.onrtctransform = event => {
  74. const transformer = event.transformer;
  75. const { operation, participantId } = transformer.options;
  76. const context = getParticipantContext(participantId);
  77. handleTransform(context, operation, transformer.readable, transformer.writable);
  78. };
  79. }