livekit-client 2.18.10 → 2.19.1

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 (63) hide show
  1. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  2. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  3. package/dist/livekit-client.esm.mjs +749 -438
  4. package/dist/livekit-client.esm.mjs.map +1 -1
  5. package/dist/livekit-client.pt.worker.js.map +1 -1
  6. package/dist/livekit-client.pt.worker.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/room/RTCEngine.d.ts +0 -3
  10. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  11. package/dist/src/room/Room.d.ts +4 -2
  12. package/dist/src/room/Room.d.ts.map +1 -1
  13. package/dist/src/room/participant/LocalParticipant.d.ts +5 -13
  14. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  15. package/dist/src/room/participant/RemoteParticipant.d.ts +5 -1
  16. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  17. package/dist/src/room/rpc/client/RpcClientManager.d.ts +39 -0
  18. package/dist/src/room/rpc/client/RpcClientManager.d.ts.map +1 -0
  19. package/dist/src/room/rpc/client/events.d.ts +8 -0
  20. package/dist/src/room/rpc/client/events.d.ts.map +1 -0
  21. package/dist/src/room/rpc/index.d.ts +6 -0
  22. package/dist/src/room/rpc/index.d.ts.map +1 -0
  23. package/dist/src/room/rpc/server/RpcServerManager.d.ts +44 -0
  24. package/dist/src/room/rpc/server/RpcServerManager.d.ts.map +1 -0
  25. package/dist/src/room/rpc/server/events.d.ts +8 -0
  26. package/dist/src/room/rpc/server/events.d.ts.map +1 -0
  27. package/dist/src/room/{rpc.d.ts → rpc/utils.d.ts} +34 -4
  28. package/dist/src/room/rpc/utils.d.ts.map +1 -0
  29. package/dist/src/room/utils.d.ts +1 -0
  30. package/dist/src/room/utils.d.ts.map +1 -1
  31. package/dist/src/version.d.ts +8 -0
  32. package/dist/src/version.d.ts.map +1 -1
  33. package/dist/ts4.2/room/RTCEngine.d.ts +0 -3
  34. package/dist/ts4.2/room/Room.d.ts +4 -2
  35. package/dist/ts4.2/room/participant/LocalParticipant.d.ts +5 -13
  36. package/dist/ts4.2/room/participant/RemoteParticipant.d.ts +5 -1
  37. package/dist/ts4.2/room/rpc/client/RpcClientManager.d.ts +43 -0
  38. package/dist/ts4.2/room/rpc/client/events.d.ts +8 -0
  39. package/dist/ts4.2/room/rpc/index.d.ts +7 -0
  40. package/dist/ts4.2/room/rpc/server/RpcServerManager.d.ts +44 -0
  41. package/dist/ts4.2/room/rpc/server/events.d.ts +8 -0
  42. package/dist/ts4.2/room/{rpc.d.ts → rpc/utils.d.ts} +34 -4
  43. package/dist/ts4.2/room/utils.d.ts +1 -0
  44. package/dist/ts4.2/version.d.ts +8 -0
  45. package/package.json +4 -2
  46. package/src/api/SignalClient.ts +1 -0
  47. package/src/room/RTCEngine.ts +4 -30
  48. package/src/room/Room.test.ts +99 -1
  49. package/src/room/Room.ts +107 -88
  50. package/src/room/participant/LocalParticipant.ts +16 -180
  51. package/src/room/participant/RemoteParticipant.ts +9 -0
  52. package/src/room/rpc/client/RpcClientManager.test.ts +430 -0
  53. package/src/room/rpc/client/RpcClientManager.ts +269 -0
  54. package/src/room/rpc/client/events.ts +9 -0
  55. package/src/room/rpc/index.ts +14 -0
  56. package/src/room/rpc/server/RpcServerManager.test.ts +471 -0
  57. package/src/room/rpc/server/RpcServerManager.ts +293 -0
  58. package/src/room/rpc/server/events.ts +9 -0
  59. package/src/room/{rpc.ts → rpc/utils.ts} +49 -8
  60. package/src/room/utils.ts +7 -1
  61. package/src/version.ts +10 -0
  62. package/dist/src/room/rpc.d.ts.map +0 -1
  63. package/src/room/rpc.test.ts +0 -301
@@ -8720,7 +8720,8 @@ function requireEvents() {
8720
8720
  }
8721
8721
  }
8722
8722
  return events.exports;
8723
- }var eventsExports = requireEvents();/*
8723
+ }var eventsExports = requireEvents();
8724
+ var EventEmitter = /*@__PURE__*/getDefaultExportFromCjs(eventsExports);/*
8724
8725
  * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
8725
8726
  *
8726
8727
  * Use of this source code is governed by a BSD-style license
@@ -11792,8 +11793,16 @@ function getMatch(exp, ua) {
11792
11793
  }
11793
11794
  function getOSVersion(ua) {
11794
11795
  return ua.includes('mac os') ? getMatch(/\(.+?(\d+_\d+(:?_\d+)?)/, ua, 1).replace(/_/g, '.') : undefined;
11795
- }var version$1 = "2.18.10";const version = version$1;
11796
- const protocolVersion = 17;/** Base error that all LiveKit specific custom errors inherit from. */
11796
+ }var version$1 = "2.19.1";const version = version$1;
11797
+ const protocolVersion = 17;
11798
+ /** Initial client protocol. */
11799
+ const CLIENT_PROTOCOL_DEFAULT = 0;
11800
+ /** Replaces RPC v1 protocol with a v2 data streams based one to support unlimited request /
11801
+ * response payload length. */
11802
+ const CLIENT_PROTOCOL_DATA_STREAM_RPC = 1;
11803
+ /** The client protocol version indicates what level of support that the client has for
11804
+ * client <-> client api interactions. */
11805
+ const clientProtocol = CLIENT_PROTOCOL_DATA_STREAM_RPC;/** Base error that all LiveKit specific custom errors inherit from. */
11797
11806
  class LivekitError extends Error {
11798
11807
  constructor(code, message, options) {
11799
11808
  super(message || 'an error has occurred');
@@ -13725,6 +13734,7 @@ function getClientInfo(capabilities) {
13725
13734
  capabilities,
13726
13735
  sdk: ClientInfo_SDK.JS,
13727
13736
  protocol: protocolVersion,
13737
+ clientProtocol,
13728
13738
  version
13729
13739
  });
13730
13740
  if (isReactNative()) {
@@ -14029,6 +14039,10 @@ function extractMaxAgeFromRequestHeaders(headers) {
14029
14039
  }
14030
14040
  function isCompressionStreamSupported() {
14031
14041
  return typeof CompressionStream !== 'undefined';
14042
+ }
14043
+ function isPublisherOfferWithJoinSupported() {
14044
+ // we have connectivity issue about publisher offer with join on firefox #1919
14045
+ return isCompressionStreamSupported() && !isFireFox();
14032
14046
  }function createRtcUrl(url, searchParams) {
14033
14047
  let useV0Path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
14034
14048
  const v0Url = createV0RtcUrl(url, searchParams);
@@ -17067,6 +17081,7 @@ function createConnectionParams(token, info, opts) {
17067
17081
  params.set('sdk', isReactNative() ? 'reactnative' : 'js');
17068
17082
  params.set('version', info.version);
17069
17083
  params.set('protocol', info.protocol.toString());
17084
+ params.set('client_protocol', info.clientProtocol.toString());
17070
17085
  if (info.deviceModel) {
17071
17086
  params.set('device_model', info.deviceModel);
17072
17087
  }
@@ -18970,118 +18985,6 @@ class PCTransportManager {
18970
18985
  }();
18971
18986
  });
18972
18987
  }
18973
- }// SPDX-FileCopyrightText: 2024 LiveKit, Inc.
18974
- //
18975
- // SPDX-License-Identifier: Apache-2.0
18976
- /**
18977
- * Specialized error handling for RPC methods.
18978
- *
18979
- * Instances of this type, when thrown in a method handler, will have their `message`
18980
- * serialized and sent across the wire. The sender will receive an equivalent error on the other side.
18981
- *
18982
- * Built-in types are included but developers may use any string, with a max length of 256 bytes.
18983
- */
18984
- class RpcError extends Error {
18985
- /**
18986
- * Creates an error object with the given code and message, plus an optional data payload.
18987
- *
18988
- * If thrown in an RPC method handler, the error will be sent back to the caller.
18989
- *
18990
- * Error codes 1001-1999 are reserved for built-in errors (see RpcError.ErrorCode for their meanings).
18991
- */
18992
- constructor(code, message, data) {
18993
- super(message);
18994
- this.code = code;
18995
- this.message = truncateBytes(message, RpcError.MAX_MESSAGE_BYTES);
18996
- this.data = data ? truncateBytes(data, RpcError.MAX_DATA_BYTES) : undefined;
18997
- }
18998
- /**
18999
- * @internal
19000
- */
19001
- static fromProto(proto) {
19002
- return new RpcError(proto.code, proto.message, proto.data);
19003
- }
19004
- /**
19005
- * @internal
19006
- */
19007
- toProto() {
19008
- return new RpcError$1({
19009
- code: this.code,
19010
- message: this.message,
19011
- data: this.data
19012
- });
19013
- }
19014
- /**
19015
- * Creates an error object from the code, with an auto-populated message.
19016
- *
19017
- * @internal
19018
- */
19019
- static builtIn(key, data) {
19020
- return new RpcError(RpcError.ErrorCode[key], RpcError.ErrorMessage[key], data);
19021
- }
19022
- }
19023
- RpcError.MAX_MESSAGE_BYTES = 256;
19024
- RpcError.MAX_DATA_BYTES = 15360; // 15 KB
19025
- RpcError.ErrorCode = {
19026
- APPLICATION_ERROR: 1500,
19027
- CONNECTION_TIMEOUT: 1501,
19028
- RESPONSE_TIMEOUT: 1502,
19029
- RECIPIENT_DISCONNECTED: 1503,
19030
- RESPONSE_PAYLOAD_TOO_LARGE: 1504,
19031
- SEND_FAILED: 1505,
19032
- UNSUPPORTED_METHOD: 1400,
19033
- RECIPIENT_NOT_FOUND: 1401,
19034
- REQUEST_PAYLOAD_TOO_LARGE: 1402,
19035
- UNSUPPORTED_SERVER: 1403,
19036
- UNSUPPORTED_VERSION: 1404
19037
- };
19038
- /**
19039
- * @internal
19040
- */
19041
- RpcError.ErrorMessage = {
19042
- APPLICATION_ERROR: 'Application error in method handler',
19043
- CONNECTION_TIMEOUT: 'Connection timeout',
19044
- RESPONSE_TIMEOUT: 'Response timeout',
19045
- RECIPIENT_DISCONNECTED: 'Recipient disconnected',
19046
- RESPONSE_PAYLOAD_TOO_LARGE: 'Response payload too large',
19047
- SEND_FAILED: 'Failed to send',
19048
- UNSUPPORTED_METHOD: 'Method not supported at destination',
19049
- RECIPIENT_NOT_FOUND: 'Recipient not found',
19050
- REQUEST_PAYLOAD_TOO_LARGE: 'Request payload too large',
19051
- UNSUPPORTED_SERVER: 'RPC not supported by server',
19052
- UNSUPPORTED_VERSION: 'Unsupported RPC version'
19053
- };
19054
- /*
19055
- * Maximum payload size for RPC requests and responses. If a payload exceeds this size,
19056
- * the RPC call will fail with a REQUEST_PAYLOAD_TOO_LARGE(1402) or RESPONSE_PAYLOAD_TOO_LARGE(1504) error.
19057
- */
19058
- const MAX_PAYLOAD_BYTES = 15360; // 15 KB
19059
- /**
19060
- * @internal
19061
- */
19062
- function byteLength(str) {
19063
- const encoder = new TextEncoder();
19064
- return encoder.encode(str).length;
19065
- }
19066
- /**
19067
- * @internal
19068
- */
19069
- function truncateBytes(str, maxBytes) {
19070
- if (byteLength(str) <= maxBytes) {
19071
- return str;
19072
- }
19073
- let low = 0;
19074
- let high = str.length;
19075
- const encoder = new TextEncoder();
19076
- while (low < high) {
19077
- const mid = Math.floor((low + high + 1) / 2);
19078
- if (encoder.encode(str.slice(0, mid)).length <= maxBytes) {
19079
- low = mid;
19080
- } else {
19081
- high = mid - 1;
19082
- }
19083
- }
19084
- return str.slice(0, low);
19085
18988
  }// Check if MediaRecorder is available
19086
18989
  const isMediaRecorderAvailable = typeof MediaRecorder !== 'undefined';
19087
18990
  // Fallback class for environments without MediaRecorder
@@ -21457,7 +21360,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21457
21360
  _this2.joinAttempts += 1;
21458
21361
  _this2.setupSignalClientCallbacks();
21459
21362
  let offerProto;
21460
- if (!useV0Path && isCompressionStreamSupported()) {
21363
+ if (!useV0Path && isPublisherOfferWithJoinSupported()) {
21461
21364
  if (!_this2.pcManager) {
21462
21365
  yield _this2.configure();
21463
21366
  _this2.createDataChannels();
@@ -21480,7 +21383,7 @@ class RTCEngine extends eventsExports.EventEmitter {
21480
21383
  _this2.latestJoinResponse = joinResponse;
21481
21384
  _this2.participantSid = (_b = joinResponse.participant) === null || _b === void 0 ? void 0 : _b.sid;
21482
21385
  _this2.subscriberPrimary = joinResponse.subscriberPrimary;
21483
- if (!useV0Path && isCompressionStreamSupported()) {
21386
+ if (!useV0Path && isPublisherOfferWithJoinSupported()) {
21484
21387
  (_c = _this2.pcManager) === null || _c === void 0 ? void 0 : _c.updateConfiguration(_this2.makeRTCConfiguration(joinResponse));
21485
21388
  } else {
21486
21389
  if (!_this2.pcManager) {
@@ -22296,29 +22199,6 @@ class RTCEngine extends eventsExports.EventEmitter {
22296
22199
  });
22297
22200
  }
22298
22201
  /** @internal */
22299
- publishRpcResponse(destinationIdentity, requestId, payload, error) {
22300
- return __awaiter(this, void 0, void 0, function* () {
22301
- const packet = new DataPacket({
22302
- destinationIdentities: [destinationIdentity],
22303
- kind: DataPacket_Kind.RELIABLE,
22304
- value: {
22305
- case: 'rpcResponse',
22306
- value: new RpcResponse({
22307
- requestId,
22308
- value: error ? {
22309
- case: 'error',
22310
- value: error.toProto()
22311
- } : {
22312
- case: 'payload',
22313
- value: payload !== null && payload !== void 0 ? payload : ''
22314
- }
22315
- })
22316
- }
22317
- });
22318
- yield this.sendDataPacket(packet, DataChannelKind.RELIABLE);
22319
- });
22320
- }
22321
- /** @internal */
22322
22202
  publishRpcAck(destinationIdentity, requestId) {
22323
22203
  return __awaiter(this, void 0, void 0, function* () {
22324
22204
  const packet = new DataPacket({
@@ -25863,112 +25743,635 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
25863
25743
  this.emit('reset');
25864
25744
  });
25865
25745
  }
25866
- }class RemoteAudioTrack extends RemoteTrack {
25867
- constructor(mediaTrack, sid, receiver, audioContext, audioOutput, loggerOptions) {
25868
- super(mediaTrack, sid, Track.Kind.Audio, receiver, loggerOptions);
25869
- this.monitorReceiver = () => __awaiter(this, void 0, void 0, function* () {
25870
- if (!this.receiver) {
25871
- this._currentBitrate = 0;
25872
- return;
25873
- }
25874
- const stats = yield this.getReceiverStats();
25875
- if (stats && this.prevStats && this.receiver) {
25876
- this._currentBitrate = computeBitrate(stats, this.prevStats);
25877
- }
25878
- this.prevStats = stats;
25879
- });
25880
- this.audioContext = audioContext;
25881
- this.webAudioPluginNodes = [];
25882
- if (audioOutput) {
25883
- this.sinkId = audioOutput.deviceId;
25884
- }
25885
- }
25746
+ }/**
25747
+ * Specialized error handling for RPC methods.
25748
+ *
25749
+ * Instances of this type, when thrown in a method handler, will have their `message`
25750
+ * serialized and sent across the wire. The sender will receive an equivalent error on the other side.
25751
+ *
25752
+ * Built-in types are included but developers may use any string, with a max length of 256 bytes.
25753
+ */
25754
+ class RpcError extends Error {
25886
25755
  /**
25887
- * sets the volume for all attached audio elements
25756
+ * Creates an error object with the given code and message, plus an optional data payload.
25757
+ *
25758
+ * If thrown in an RPC method handler, the error will be sent back to the caller.
25759
+ *
25760
+ * Error codes 1001-1999 are reserved for built-in errors (see RpcError.ErrorCode for their meanings).
25888
25761
  */
25889
- setVolume(volume) {
25890
- var _a;
25891
- for (const el of this.attachedElements) {
25892
- if (this.audioContext) {
25893
- (_a = this.gainNode) === null || _a === void 0 ? void 0 : _a.gain.setTargetAtTime(volume, 0, 0.1);
25894
- } else {
25895
- el.volume = volume;
25896
- }
25897
- }
25898
- if (isReactNative()) {
25899
- // @ts-ignore
25900
- this._mediaStreamTrack._setVolume(volume);
25762
+ constructor(code, message, data, options) {
25763
+ super(message);
25764
+ this.code = code;
25765
+ this.message = truncateBytes(message, RpcError.MAX_MESSAGE_BYTES);
25766
+ this.data = data ? truncateBytes(data, RpcError.MAX_DATA_BYTES) : undefined;
25767
+ if (typeof (options === null || options === void 0 ? void 0 : options.cause) !== 'undefined') {
25768
+ this.cause = options === null || options === void 0 ? void 0 : options.cause;
25901
25769
  }
25902
- this.elementVolume = volume;
25903
25770
  }
25904
25771
  /**
25905
- * gets the volume of attached audio elements (loudest)
25772
+ * @internal
25906
25773
  */
25907
- getVolume() {
25908
- if (this.elementVolume) {
25909
- return this.elementVolume;
25910
- }
25911
- if (isReactNative()) {
25912
- // RN volume value defaults to 1.0 if hasn't been changed.
25913
- return 1.0;
25914
- }
25915
- let highestVolume = 0;
25916
- this.attachedElements.forEach(element => {
25917
- if (element.volume > highestVolume) {
25918
- highestVolume = element.volume;
25919
- }
25920
- });
25921
- return highestVolume;
25774
+ static fromProto(proto) {
25775
+ return new RpcError(proto.code, proto.message, proto.data);
25922
25776
  }
25923
25777
  /**
25924
- * calls setSinkId on all attached elements, if supported
25925
- * @param deviceId audio output device
25778
+ * @internal
25926
25779
  */
25927
- setSinkId(deviceId) {
25928
- return __awaiter(this, void 0, void 0, function* () {
25929
- this.sinkId = deviceId;
25930
- yield Promise.all(this.attachedElements.map(elm => {
25931
- if (!supportsSetSinkId(elm)) {
25932
- return;
25933
- }
25934
- /* @ts-ignore */
25935
- return elm.setSinkId(deviceId);
25936
- }));
25780
+ toProto() {
25781
+ return new RpcError$1({
25782
+ code: this.code,
25783
+ message: this.message,
25784
+ data: this.data
25937
25785
  });
25938
25786
  }
25939
- attach(element) {
25940
- const needsNewWebAudioConnection = this.attachedElements.length === 0;
25941
- if (!element) {
25942
- element = super.attach();
25943
- } else {
25944
- super.attach(element);
25945
- }
25946
- if (this.sinkId && supportsSetSinkId(element)) {
25947
- element.setSinkId(this.sinkId).catch(e => {
25948
- this.log.error('Failed to set sink id on remote audio track', e, this.logContext);
25949
- });
25950
- }
25951
- if (this.audioContext && needsNewWebAudioConnection) {
25952
- this.log.debug('using audio context mapping', this.logContext);
25953
- this.connectWebAudio(this.audioContext, element);
25954
- element.volume = 0;
25955
- element.muted = true;
25956
- }
25957
- if (this.elementVolume) {
25958
- // make sure volume setting is being applied to the newly attached element
25959
- this.setVolume(this.elementVolume);
25960
- }
25961
- return element;
25787
+ /**
25788
+ * Creates an error object from the code, with an auto-populated message.
25789
+ *
25790
+ * @internal
25791
+ */
25792
+ static builtIn(key, data, options) {
25793
+ return new RpcError(RpcError.ErrorCode[key], RpcError.ErrorMessage[key], data, options);
25962
25794
  }
25963
- detach(element) {
25964
- let detached;
25965
- if (!element) {
25966
- detached = super.detach();
25967
- this.disconnectWebAudio();
25968
- } else {
25969
- detached = super.detach(element);
25970
- // if there are still any attached elements after detaching, connect webaudio to the first element that's left
25971
- // disconnect webaudio otherwise
25795
+ }
25796
+ RpcError.MAX_MESSAGE_BYTES = 256;
25797
+ RpcError.MAX_DATA_BYTES = 15360; // 15 KB
25798
+ RpcError.ErrorCode = {
25799
+ APPLICATION_ERROR: 1500,
25800
+ CONNECTION_TIMEOUT: 1501,
25801
+ RESPONSE_TIMEOUT: 1502,
25802
+ RECIPIENT_DISCONNECTED: 1503,
25803
+ RESPONSE_PAYLOAD_TOO_LARGE: 1504,
25804
+ SEND_FAILED: 1505,
25805
+ UNSUPPORTED_METHOD: 1400,
25806
+ RECIPIENT_NOT_FOUND: 1401,
25807
+ REQUEST_PAYLOAD_TOO_LARGE: 1402,
25808
+ UNSUPPORTED_SERVER: 1403,
25809
+ UNSUPPORTED_VERSION: 1404
25810
+ };
25811
+ /**
25812
+ * @internal
25813
+ */
25814
+ RpcError.ErrorMessage = {
25815
+ APPLICATION_ERROR: 'Application error in method handler',
25816
+ CONNECTION_TIMEOUT: 'Connection timeout',
25817
+ RESPONSE_TIMEOUT: 'Response timeout',
25818
+ RECIPIENT_DISCONNECTED: 'Recipient disconnected',
25819
+ RESPONSE_PAYLOAD_TOO_LARGE: 'Response payload too large',
25820
+ SEND_FAILED: 'Failed to send',
25821
+ UNSUPPORTED_METHOD: 'Method not supported at destination',
25822
+ RECIPIENT_NOT_FOUND: 'Recipient not found',
25823
+ REQUEST_PAYLOAD_TOO_LARGE: 'Request payload too large',
25824
+ UNSUPPORTED_SERVER: 'RPC not supported by server',
25825
+ UNSUPPORTED_VERSION: 'Unsupported RPC version'
25826
+ };
25827
+ /*
25828
+ * Maximum payload size for RPC requests and responses for clients with a clientProtocol of less
25829
+ * than CLIENT_PROTOCOL_DATA_STREAM_RPC.
25830
+ *
25831
+ * If a payload exceeds this size and the remote client does not support compression,
25832
+ * the RPC call will fail with a REQUEST_PAYLOAD_TOO_LARGE(1402) or RESPONSE_PAYLOAD_TOO_LARGE(1504) error.
25833
+ */
25834
+ const MAX_V1_PAYLOAD_BYTES = 15360; // 15 KB
25835
+ /**
25836
+ * Topic used for v2 RPC request data streams.
25837
+ * @internal
25838
+ */
25839
+ const RPC_REQUEST_DATA_STREAM_TOPIC = 'lk.rpc_request';
25840
+ /**
25841
+ * Topic used for v2 RPC response data streams.
25842
+ * @internal
25843
+ */
25844
+ const RPC_RESPONSE_DATA_STREAM_TOPIC = 'lk.rpc_response';
25845
+ /** @internal */
25846
+ var RpcRequestAttrs;
25847
+ (function (RpcRequestAttrs) {
25848
+ RpcRequestAttrs["RPC_REQUEST_ID"] = "lk.rpc_request_id";
25849
+ RpcRequestAttrs["RPC_REQUEST_METHOD"] = "lk.rpc_request_method";
25850
+ RpcRequestAttrs["RPC_REQUEST_RESPONSE_TIMEOUT_MS"] = "lk.rpc_request_response_timeout_ms";
25851
+ RpcRequestAttrs["RPC_REQUEST_VERSION"] = "lk.rpc_request_version";
25852
+ })(RpcRequestAttrs || (RpcRequestAttrs = {}));
25853
+ /** Initial version of rpc which uses RpcRequest / RpcResponse messages.
25854
+ * @internal
25855
+ **/
25856
+ const RPC_VERSION_V1 = 1;
25857
+ /** Rpc version backed by data streams instead of RpcRequest / RpcResponse.
25858
+ * @internal
25859
+ **/
25860
+ const RPC_VERSION_V2 = 2;
25861
+ /**
25862
+ * @internal
25863
+ */
25864
+ function byteLength(str) {
25865
+ const encoder = new TextEncoder();
25866
+ return encoder.encode(str).length;
25867
+ }
25868
+ /**
25869
+ * @internal
25870
+ */
25871
+ function truncateBytes(str, maxBytes) {
25872
+ if (byteLength(str) <= maxBytes) {
25873
+ return str;
25874
+ }
25875
+ let low = 0;
25876
+ let high = str.length;
25877
+ const encoder = new TextEncoder();
25878
+ while (low < high) {
25879
+ const mid = Math.floor((low + high + 1) / 2);
25880
+ if (encoder.encode(str.slice(0, mid)).length <= maxBytes) {
25881
+ low = mid;
25882
+ } else {
25883
+ high = mid - 1;
25884
+ }
25885
+ }
25886
+ return str.slice(0, low);
25887
+ }/**
25888
+ * Manages the client (caller) side of RPC: sending requests, tracking pending
25889
+ * ack/response state, and handling incoming ack/response packets.
25890
+ * @internal
25891
+ */
25892
+ class RpcClientManager extends EventEmitter {
25893
+ constructor(log, outgoingDataStreamManager, getRemoteParticipantClientProtocol, getServerVersion) {
25894
+ super();
25895
+ this.pendingAcks = new Map();
25896
+ this.pendingResponses = new Map();
25897
+ this.log = log;
25898
+ this.outgoingDataStreamManager = outgoingDataStreamManager;
25899
+ this.getRemoteParticipantClientProtocol = getRemoteParticipantClientProtocol;
25900
+ this.getServerVersion = getServerVersion;
25901
+ }
25902
+ performRpc(_a) {
25903
+ return __awaiter(this, arguments, void 0, function (_ref) {
25904
+ var _this = this;
25905
+ let {
25906
+ destinationIdentity,
25907
+ method,
25908
+ payload,
25909
+ responseTimeout: responseTimeoutMs = 15000
25910
+ } = _ref;
25911
+ return function* () {
25912
+ const maxRoundTripLatencyMs = 7000;
25913
+ const minEffectiveTimeoutMs = maxRoundTripLatencyMs + 1000;
25914
+ const remoteClientProtocol = _this.getRemoteParticipantClientProtocol(destinationIdentity);
25915
+ const payloadBytes = byteLength(payload);
25916
+ // Only enforce the legacy size limit when on rpc v1
25917
+ if (payloadBytes > MAX_V1_PAYLOAD_BYTES && remoteClientProtocol < CLIENT_PROTOCOL_DATA_STREAM_RPC) {
25918
+ throw RpcError.builtIn('REQUEST_PAYLOAD_TOO_LARGE');
25919
+ }
25920
+ const serverVersion = _this.getServerVersion();
25921
+ if (serverVersion && compareVersions(serverVersion, '1.8.0') < 0) {
25922
+ throw RpcError.builtIn('UNSUPPORTED_SERVER');
25923
+ }
25924
+ const effectiveTimeoutMs = Math.max(responseTimeoutMs, minEffectiveTimeoutMs);
25925
+ const id = crypto.randomUUID();
25926
+ const completionFuture = new Future();
25927
+ const ackTimeoutId = setTimeout(() => {
25928
+ var _a;
25929
+ _this.pendingAcks.delete(id);
25930
+ (_a = completionFuture.reject) === null || _a === void 0 ? void 0 : _a.call(completionFuture, RpcError.builtIn('CONNECTION_TIMEOUT'));
25931
+ _this.pendingResponses.delete(id);
25932
+ clearTimeout(responseTimeoutId);
25933
+ }, maxRoundTripLatencyMs);
25934
+ _this.pendingAcks.set(id, {
25935
+ resolve: () => {
25936
+ clearTimeout(ackTimeoutId);
25937
+ },
25938
+ participantIdentity: destinationIdentity
25939
+ });
25940
+ _this.pendingResponses.set(id, {
25941
+ completionFuture,
25942
+ participantIdentity: destinationIdentity
25943
+ });
25944
+ yield _this.publishRpcRequest(destinationIdentity, id, method, payload, effectiveTimeoutMs, remoteClientProtocol);
25945
+ const responseTimeoutId = setTimeout(() => {
25946
+ var _a;
25947
+ _this.pendingResponses.delete(id);
25948
+ (_a = completionFuture.reject) === null || _a === void 0 ? void 0 : _a.call(completionFuture, RpcError.builtIn('RESPONSE_TIMEOUT'));
25949
+ }, responseTimeoutMs);
25950
+ const completionPromise = completionFuture.promise.finally(() => {
25951
+ clearTimeout(responseTimeoutId);
25952
+ if (_this.pendingAcks.has(id)) {
25953
+ _this.log.warn('RPC response received before ack', id);
25954
+ _this.pendingAcks.delete(id);
25955
+ clearTimeout(ackTimeoutId);
25956
+ }
25957
+ });
25958
+ return [id, completionPromise];
25959
+ }();
25960
+ });
25961
+ }
25962
+ publishRpcRequest(destinationIdentity, requestId, method, payload, responseTimeout, remoteClientProtocol) {
25963
+ return __awaiter(this, void 0, void 0, function* () {
25964
+ if (remoteClientProtocol >= CLIENT_PROTOCOL_DATA_STREAM_RPC) {
25965
+ // Send payload as a data stream - a "version 2" rpc request.
25966
+ const writer = yield this.outgoingDataStreamManager.streamText({
25967
+ topic: RPC_REQUEST_DATA_STREAM_TOPIC,
25968
+ destinationIdentities: [destinationIdentity],
25969
+ attributes: {
25970
+ [RpcRequestAttrs.RPC_REQUEST_ID]: requestId,
25971
+ [RpcRequestAttrs.RPC_REQUEST_METHOD]: method,
25972
+ [RpcRequestAttrs.RPC_REQUEST_RESPONSE_TIMEOUT_MS]: "".concat(responseTimeout),
25973
+ [RpcRequestAttrs.RPC_REQUEST_VERSION]: "".concat(RPC_VERSION_V2)
25974
+ }
25975
+ });
25976
+ yield writer.write(payload);
25977
+ yield writer.close();
25978
+ return;
25979
+ }
25980
+ // Fallback to sending a literal RpcRequest - a "version 1" rpc request.
25981
+ this.emit('sendDataPacket', {
25982
+ packet: new DataPacket({
25983
+ destinationIdentities: [destinationIdentity],
25984
+ kind: DataPacket_Kind.RELIABLE,
25985
+ value: {
25986
+ case: 'rpcRequest',
25987
+ value: new RpcRequest({
25988
+ id: requestId,
25989
+ method,
25990
+ payload,
25991
+ responseTimeoutMs: responseTimeout,
25992
+ version: RPC_VERSION_V1
25993
+ })
25994
+ }
25995
+ })
25996
+ });
25997
+ });
25998
+ }
25999
+ /**
26000
+ * Handle an incoming data stream containing an RPC response payload.
26001
+ * @internal
26002
+ */
26003
+ handleIncomingDataStream(reader, senderIdentity, attributes) {
26004
+ return __awaiter(this, void 0, void 0, function* () {
26005
+ const associatedRequestId = attributes[RpcRequestAttrs.RPC_REQUEST_ID];
26006
+ if (!associatedRequestId) {
26007
+ this.log.warn("RPC data stream malformed: ".concat(RpcRequestAttrs.RPC_REQUEST_ID, " not set."));
26008
+ // NOTE: no response can be sent here, because there's no request id so associate
26009
+ // so logging is the best we can do here.
26010
+ return;
26011
+ }
26012
+ const pending = this.pendingResponses.get(associatedRequestId);
26013
+ if (pending && pending.participantIdentity !== senderIdentity) {
26014
+ this.log.warn("RPC response stream for ".concat(associatedRequestId, " arrived from unexpected sender ").concat(senderIdentity, ", expected ").concat(pending.participantIdentity, ". Ignoring."));
26015
+ return;
26016
+ }
26017
+ let payload;
26018
+ try {
26019
+ payload = yield reader.readAll();
26020
+ } catch (e) {
26021
+ this.log.warn("Error reading RPC response payload: ".concat(e));
26022
+ this.handleIncomingRpcResponseFailure(associatedRequestId, RpcError.builtIn('APPLICATION_ERROR', 'Error reading RPC response payload', {
26023
+ cause: e
26024
+ }));
26025
+ return;
26026
+ }
26027
+ this.handleIncomingRpcResponseSuccess(associatedRequestId, payload);
26028
+ });
26029
+ }
26030
+ /** @internal */
26031
+ handleIncomingRpcResponseSuccess(requestId, payload) {
26032
+ var _a, _b;
26033
+ const handler = this.pendingResponses.get(requestId);
26034
+ if (handler) {
26035
+ (_b = (_a = handler.completionFuture).resolve) === null || _b === void 0 ? void 0 : _b.call(_a, payload);
26036
+ this.pendingResponses.delete(requestId);
26037
+ } else {
26038
+ this.log.error('Response received for unexpected RPC request', requestId);
26039
+ }
26040
+ }
26041
+ /** @internal */
26042
+ handleIncomingRpcResponseFailure(requestId, error) {
26043
+ var _a, _b;
26044
+ const handler = this.pendingResponses.get(requestId);
26045
+ if (handler) {
26046
+ (_b = (_a = handler.completionFuture).reject) === null || _b === void 0 ? void 0 : _b.call(_a, error);
26047
+ this.pendingResponses.delete(requestId);
26048
+ } else {
26049
+ this.log.error('Response received for unexpected RPC request', requestId);
26050
+ }
26051
+ }
26052
+ /** @internal */
26053
+ handleIncomingRpcAck(requestId) {
26054
+ const handler = this.pendingAcks.get(requestId);
26055
+ if (handler) {
26056
+ handler.resolve();
26057
+ this.pendingAcks.delete(requestId);
26058
+ } else {
26059
+ this.log.error("Ack received for unexpected RPC request: ".concat(requestId));
26060
+ }
26061
+ }
26062
+ /** @internal */
26063
+ handleParticipantDisconnected(participantIdentity) {
26064
+ var _a;
26065
+ for (const [id, {
26066
+ participantIdentity: pendingIdentity
26067
+ }] of this.pendingAcks) {
26068
+ if (pendingIdentity === participantIdentity) {
26069
+ this.pendingAcks.delete(id);
26070
+ }
26071
+ }
26072
+ for (const [id, {
26073
+ participantIdentity: pendingIdentity,
26074
+ completionFuture
26075
+ }] of this.pendingResponses) {
26076
+ if (pendingIdentity === participantIdentity) {
26077
+ (_a = completionFuture.reject) === null || _a === void 0 ? void 0 : _a.call(completionFuture, RpcError.builtIn('RECIPIENT_DISCONNECTED'));
26078
+ this.pendingResponses.delete(id);
26079
+ }
26080
+ }
26081
+ }
26082
+ }/**
26083
+ * Manages the server (handler) side of RPC: processing incoming requests,
26084
+ * managing registered method handlers, and sending responses.
26085
+ * @internal
26086
+ */
26087
+ class RpcServerManager extends EventEmitter {
26088
+ constructor(log, outgoingDataStreamManager, getRemoteParticipantClientProtocol) {
26089
+ super();
26090
+ this.rpcHandlers = new Map();
26091
+ this.log = log;
26092
+ this.outgoingDataStreamManager = outgoingDataStreamManager;
26093
+ this.getRemoteParticipantClientProtocol = getRemoteParticipantClientProtocol;
26094
+ }
26095
+ registerRpcMethod(method, handler) {
26096
+ if (this.rpcHandlers.has(method)) {
26097
+ throw Error("RPC handler already registered for method ".concat(method, ", unregisterRpcMethod before trying to register again"));
26098
+ }
26099
+ this.rpcHandlers.set(method, handler);
26100
+ }
26101
+ unregisterRpcMethod(method) {
26102
+ this.rpcHandlers.delete(method);
26103
+ }
26104
+ /**
26105
+ * Handle an incoming RPCRequest message containing a payload.
26106
+ * This handles "version 1" of rpc requests.
26107
+ * @internal
26108
+ */
26109
+ handleIncomingRpcRequest(callerIdentity, rpcRequest) {
26110
+ return __awaiter(this, void 0, void 0, function* () {
26111
+ var _a;
26112
+ this.publishRpcAck(callerIdentity, rpcRequest.id);
26113
+ if (rpcRequest.version !== 1) {
26114
+ this.publishRpcResponsePacket(callerIdentity, rpcRequest.id, null, RpcError.builtIn('UNSUPPORTED_VERSION'));
26115
+ return;
26116
+ }
26117
+ const handler = this.rpcHandlers.get(rpcRequest.method);
26118
+ if (!handler) {
26119
+ this.publishRpcResponsePacket(callerIdentity, rpcRequest.id, null, RpcError.builtIn('UNSUPPORTED_METHOD'));
26120
+ return;
26121
+ }
26122
+ let response;
26123
+ try {
26124
+ response = yield handler({
26125
+ requestId: rpcRequest.id,
26126
+ callerIdentity,
26127
+ payload: rpcRequest.payload,
26128
+ responseTimeout: rpcRequest.responseTimeoutMs
26129
+ });
26130
+ } catch (error) {
26131
+ let responseError;
26132
+ if (error instanceof RpcError) {
26133
+ responseError = error;
26134
+ } else {
26135
+ this.log.warn("Uncaught error returned by RPC handler for ".concat(rpcRequest.method, ". Returning APPLICATION_ERROR instead."), error);
26136
+ responseError = RpcError.builtIn('APPLICATION_ERROR', "Uncaught error: ".concat((_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error), {
26137
+ cause: error
26138
+ });
26139
+ }
26140
+ this.publishRpcResponsePacket(callerIdentity, rpcRequest.id, null, responseError);
26141
+ return;
26142
+ }
26143
+ yield this.publishRpcResponse(callerIdentity, rpcRequest.id, response !== null && response !== void 0 ? response : '');
26144
+ });
26145
+ }
26146
+ /**
26147
+ * Handle an incoming data stream containing a RPC request payload.
26148
+ * This handles "version 2" of rpc requests.
26149
+ * @internal
26150
+ */
26151
+ handleIncomingDataStream(reader, callerIdentity, dataStreamAttrs) {
26152
+ return __awaiter(this, void 0, void 0, function* () {
26153
+ const requestId = dataStreamAttrs[RpcRequestAttrs.RPC_REQUEST_ID];
26154
+ const method = dataStreamAttrs[RpcRequestAttrs.RPC_REQUEST_METHOD];
26155
+ const responseTimeout = parseInt(dataStreamAttrs[RpcRequestAttrs.RPC_REQUEST_RESPONSE_TIMEOUT_MS], 10);
26156
+ const version = parseInt(dataStreamAttrs[RpcRequestAttrs.RPC_REQUEST_VERSION], 10);
26157
+ if (!requestId || !method || Number.isNaN(responseTimeout) || Number.isNaN(version)) {
26158
+ this.log.warn("RPC data stream malformed: ".concat(RpcRequestAttrs.RPC_REQUEST_ID, " / ").concat(RpcRequestAttrs.RPC_REQUEST_METHOD, " / ").concat(RpcRequestAttrs.RPC_REQUEST_RESPONSE_TIMEOUT_MS, " / ").concat(RpcRequestAttrs.RPC_REQUEST_VERSION, " not set."));
26159
+ this.publishRpcResponsePacket(callerIdentity, requestId, null, RpcError.builtIn('APPLICATION_ERROR', 'RPC data stream malformed'));
26160
+ return;
26161
+ }
26162
+ this.publishRpcAck(callerIdentity, requestId);
26163
+ if (version !== RPC_VERSION_V2) {
26164
+ this.publishRpcResponsePacket(callerIdentity, requestId, null, RpcError.builtIn('UNSUPPORTED_VERSION'));
26165
+ return;
26166
+ }
26167
+ let payload;
26168
+ try {
26169
+ payload = yield reader.readAll();
26170
+ } catch (e) {
26171
+ this.log.warn("Error reading RPC request payload: ".concat(e));
26172
+ this.publishRpcResponsePacket(callerIdentity, requestId, null, RpcError.builtIn('APPLICATION_ERROR', 'Error reading RPC request payload', {
26173
+ cause: e
26174
+ }));
26175
+ return;
26176
+ }
26177
+ const handler = this.rpcHandlers.get(method);
26178
+ if (!handler) {
26179
+ this.publishRpcResponsePacket(callerIdentity, requestId, null, RpcError.builtIn('UNSUPPORTED_METHOD'));
26180
+ return;
26181
+ }
26182
+ let response;
26183
+ try {
26184
+ response = yield handler({
26185
+ requestId,
26186
+ callerIdentity,
26187
+ payload,
26188
+ responseTimeout
26189
+ });
26190
+ } catch (error) {
26191
+ let responseError;
26192
+ if (error instanceof RpcError) {
26193
+ responseError = error;
26194
+ } else {
26195
+ this.log.warn("Uncaught error returned by RPC handler for ".concat(method, ". Returning APPLICATION_ERROR instead."), error);
26196
+ responseError = RpcError.builtIn('APPLICATION_ERROR');
26197
+ }
26198
+ this.publishRpcResponsePacket(callerIdentity, requestId, null, responseError);
26199
+ return;
26200
+ }
26201
+ yield this.publishRpcResponse(callerIdentity, requestId, response !== null && response !== void 0 ? response : '');
26202
+ });
26203
+ }
26204
+ publishRpcAck(destinationIdentity, requestId) {
26205
+ this.emit('sendDataPacket', {
26206
+ packet: new DataPacket({
26207
+ destinationIdentities: [destinationIdentity],
26208
+ kind: DataPacket_Kind.RELIABLE,
26209
+ value: {
26210
+ case: 'rpcAck',
26211
+ value: new RpcAck({
26212
+ requestId
26213
+ })
26214
+ }
26215
+ })
26216
+ });
26217
+ }
26218
+ publishRpcResponsePacket(destinationIdentity, requestId, payload, error) {
26219
+ this.emit('sendDataPacket', {
26220
+ packet: new DataPacket({
26221
+ destinationIdentities: [destinationIdentity],
26222
+ kind: DataPacket_Kind.RELIABLE,
26223
+ value: {
26224
+ case: 'rpcResponse',
26225
+ value: new RpcResponse({
26226
+ requestId,
26227
+ value: error ? {
26228
+ case: 'error',
26229
+ value: error.toProto()
26230
+ } : {
26231
+ case: 'payload',
26232
+ value: payload !== null && payload !== void 0 ? payload : ''
26233
+ }
26234
+ })
26235
+ }
26236
+ })
26237
+ });
26238
+ }
26239
+ /**
26240
+ * Send a successful RPC response payload, choosing the transport based on
26241
+ * the caller's client protocol version.
26242
+ */
26243
+ publishRpcResponse(destinationIdentity, requestId, payload) {
26244
+ return __awaiter(this, void 0, void 0, function* () {
26245
+ const callerClientProtocol = this.getRemoteParticipantClientProtocol(destinationIdentity);
26246
+ if (callerClientProtocol >= CLIENT_PROTOCOL_DATA_STREAM_RPC) {
26247
+ // Send response as a data stream
26248
+ const writer = yield this.outgoingDataStreamManager.streamText({
26249
+ topic: RPC_RESPONSE_DATA_STREAM_TOPIC,
26250
+ destinationIdentities: [destinationIdentity],
26251
+ attributes: {
26252
+ [RpcRequestAttrs.RPC_REQUEST_ID]: requestId
26253
+ }
26254
+ });
26255
+ yield writer.write(payload);
26256
+ yield writer.close();
26257
+ return;
26258
+ }
26259
+ // Legacy client: enforce size limit and send uncompressed payload inline
26260
+ const responseBytes = byteLength(payload);
26261
+ if (responseBytes > MAX_V1_PAYLOAD_BYTES) {
26262
+ this.log.warn("RPC Response payload too large for request ".concat(requestId, ". To send larger responses, consider updating the sending client."));
26263
+ this.publishRpcResponsePacket(destinationIdentity, requestId, null, RpcError.builtIn('RESPONSE_PAYLOAD_TOO_LARGE'));
26264
+ return;
26265
+ }
26266
+ this.publishRpcResponsePacket(destinationIdentity, requestId, payload, null);
26267
+ });
26268
+ }
26269
+ }class RemoteAudioTrack extends RemoteTrack {
26270
+ constructor(mediaTrack, sid, receiver, audioContext, audioOutput, loggerOptions) {
26271
+ super(mediaTrack, sid, Track.Kind.Audio, receiver, loggerOptions);
26272
+ this.monitorReceiver = () => __awaiter(this, void 0, void 0, function* () {
26273
+ if (!this.receiver) {
26274
+ this._currentBitrate = 0;
26275
+ return;
26276
+ }
26277
+ const stats = yield this.getReceiverStats();
26278
+ if (stats && this.prevStats && this.receiver) {
26279
+ this._currentBitrate = computeBitrate(stats, this.prevStats);
26280
+ }
26281
+ this.prevStats = stats;
26282
+ });
26283
+ this.audioContext = audioContext;
26284
+ this.webAudioPluginNodes = [];
26285
+ if (audioOutput) {
26286
+ this.sinkId = audioOutput.deviceId;
26287
+ }
26288
+ }
26289
+ /**
26290
+ * sets the volume for all attached audio elements
26291
+ */
26292
+ setVolume(volume) {
26293
+ var _a;
26294
+ for (const el of this.attachedElements) {
26295
+ if (this.audioContext) {
26296
+ (_a = this.gainNode) === null || _a === void 0 ? void 0 : _a.gain.setTargetAtTime(volume, 0, 0.1);
26297
+ } else {
26298
+ el.volume = volume;
26299
+ }
26300
+ }
26301
+ if (isReactNative()) {
26302
+ // @ts-ignore
26303
+ this._mediaStreamTrack._setVolume(volume);
26304
+ }
26305
+ this.elementVolume = volume;
26306
+ }
26307
+ /**
26308
+ * gets the volume of attached audio elements (loudest)
26309
+ */
26310
+ getVolume() {
26311
+ if (this.elementVolume) {
26312
+ return this.elementVolume;
26313
+ }
26314
+ if (isReactNative()) {
26315
+ // RN volume value defaults to 1.0 if hasn't been changed.
26316
+ return 1.0;
26317
+ }
26318
+ let highestVolume = 0;
26319
+ this.attachedElements.forEach(element => {
26320
+ if (element.volume > highestVolume) {
26321
+ highestVolume = element.volume;
26322
+ }
26323
+ });
26324
+ return highestVolume;
26325
+ }
26326
+ /**
26327
+ * calls setSinkId on all attached elements, if supported
26328
+ * @param deviceId audio output device
26329
+ */
26330
+ setSinkId(deviceId) {
26331
+ return __awaiter(this, void 0, void 0, function* () {
26332
+ this.sinkId = deviceId;
26333
+ yield Promise.all(this.attachedElements.map(elm => {
26334
+ if (!supportsSetSinkId(elm)) {
26335
+ return;
26336
+ }
26337
+ /* @ts-ignore */
26338
+ return elm.setSinkId(deviceId);
26339
+ }));
26340
+ });
26341
+ }
26342
+ attach(element) {
26343
+ const needsNewWebAudioConnection = this.attachedElements.length === 0;
26344
+ if (!element) {
26345
+ element = super.attach();
26346
+ } else {
26347
+ super.attach(element);
26348
+ }
26349
+ if (this.sinkId && supportsSetSinkId(element)) {
26350
+ element.setSinkId(this.sinkId).catch(e => {
26351
+ this.log.error('Failed to set sink id on remote audio track', e, this.logContext);
26352
+ });
26353
+ }
26354
+ if (this.audioContext && needsNewWebAudioConnection) {
26355
+ this.log.debug('using audio context mapping', this.logContext);
26356
+ this.connectWebAudio(this.audioContext, element);
26357
+ element.volume = 0;
26358
+ element.muted = true;
26359
+ }
26360
+ if (this.elementVolume) {
26361
+ // make sure volume setting is being applied to the newly attached element
26362
+ this.setVolume(this.elementVolume);
26363
+ }
26364
+ return element;
26365
+ }
26366
+ detach(element) {
26367
+ let detached;
26368
+ if (!element) {
26369
+ detached = super.detach();
26370
+ this.disconnectWebAudio();
26371
+ } else {
26372
+ detached = super.detach(element);
26373
+ // if there are still any attached elements after detaching, connect webaudio to the first element that's left
26374
+ // disconnect webaudio otherwise
25972
26375
  if (this.audioContext) {
25973
26376
  if (this.attachedElements.length > 0) {
25974
26377
  this.connectWebAudio(this.audioContext, this.attachedElements[0]);
@@ -26726,7 +27129,7 @@ class Participant extends eventsExports.EventEmitter {
26726
27129
  });
26727
27130
  }class LocalParticipant extends Participant {
26728
27131
  /** @internal */
26729
- constructor(sid, identity, engine, options, roomRpcHandlers, roomOutgoingDataStreamManager, roomOutgoingDataTrackManager) {
27132
+ constructor(sid, identity, engine, options, roomOutgoingDataStreamManager, roomOutgoingDataTrackManager, rpcClientManager, rpcServerManager) {
26730
27133
  super(sid, identity, undefined, undefined, undefined, {
26731
27134
  loggerName: options.loggerName,
26732
27135
  loggerContextCb: () => this.engine.logContext
@@ -26738,8 +27141,6 @@ class Participant extends eventsExports.EventEmitter {
26738
27141
  this.encryptionType = Encryption_Type.NONE;
26739
27142
  this.e2eeStateMutex = new _();
26740
27143
  this.enabledPublishVideoCodecs = [];
26741
- this.pendingAcks = new Map();
26742
- this.pendingResponses = new Map();
26743
27144
  this.handleReconnecting = () => {
26744
27145
  if (!this.reconnectFuture) {
26745
27146
  this.reconnectFuture = new Future();
@@ -26820,25 +27221,6 @@ class Participant extends eventsExports.EventEmitter {
26820
27221
  }
26821
27222
  }
26822
27223
  };
26823
- this.handleDataPacket = packet => {
26824
- switch (packet.value.case) {
26825
- case 'rpcResponse':
26826
- let rpcResponse = packet.value.value;
26827
- let payload = null;
26828
- let error = null;
26829
- if (rpcResponse.value.case === 'payload') {
26830
- payload = rpcResponse.value.value;
26831
- } else if (rpcResponse.value.case === 'error') {
26832
- error = RpcError.fromProto(rpcResponse.value.value);
26833
- }
26834
- this.handleIncomingRpcResponse(rpcResponse.requestId, payload, error);
26835
- break;
26836
- case 'rpcAck':
26837
- let rpcAck = packet.value.value;
26838
- this.handleIncomingRpcAck(rpcAck.requestId);
26839
- break;
26840
- }
26841
- };
26842
27224
  this.updateTrackSubscriptionPermissions = () => {
26843
27225
  this.log.debug('updating track subscription permissions', {
26844
27226
  allParticipantsAllowed: this.allParticipantsAllowedToSubscribe,
@@ -26988,9 +27370,10 @@ class Participant extends eventsExports.EventEmitter {
26988
27370
  this.setupEngine(engine);
26989
27371
  this.activeDeviceMap = new Map([['audioinput', 'default'], ['videoinput', 'default'], ['audiooutput', 'default']]);
26990
27372
  this.pendingSignalRequests = new Map();
26991
- this.rpcHandlers = roomRpcHandlers;
26992
27373
  this.roomOutgoingDataStreamManager = roomOutgoingDataStreamManager;
26993
27374
  this.roomOutgoingDataTrackManager = roomOutgoingDataTrackManager;
27375
+ this.rpcClientManager = rpcClientManager;
27376
+ this.rpcServerManager = rpcServerManager;
26994
27377
  }
26995
27378
  get lastCameraError() {
26996
27379
  return this.cameraError;
@@ -27033,7 +27416,7 @@ class Participant extends eventsExports.EventEmitter {
27033
27416
  if ((_a = this.signalConnectedFuture) === null || _a === void 0 ? void 0 : _a.isResolved) {
27034
27417
  this.signalConnectedFuture = undefined;
27035
27418
  }
27036
- this.engine.on(EngineEvent.Connected, this.handleReconnected).on(EngineEvent.SignalConnected, this.handleSignalConnected).on(EngineEvent.SignalRestarted, this.handleReconnected).on(EngineEvent.SignalResumed, this.handleReconnected).on(EngineEvent.Restarting, this.handleReconnecting).on(EngineEvent.Resuming, this.handleReconnecting).on(EngineEvent.LocalTrackUnpublished, this.handleLocalTrackUnpublished).on(EngineEvent.SubscribedQualityUpdate, this.handleSubscribedQualityUpdate).on(EngineEvent.Closing, this.handleClosing).on(EngineEvent.SignalRequestResponse, this.handleSignalRequestResponse).on(EngineEvent.DataPacketReceived, this.handleDataPacket);
27419
+ this.engine.on(EngineEvent.Connected, this.handleReconnected).on(EngineEvent.SignalConnected, this.handleSignalConnected).on(EngineEvent.SignalRestarted, this.handleReconnected).on(EngineEvent.SignalResumed, this.handleReconnected).on(EngineEvent.Restarting, this.handleReconnecting).on(EngineEvent.Resuming, this.handleReconnecting).on(EngineEvent.LocalTrackUnpublished, this.handleLocalTrackUnpublished).on(EngineEvent.SubscribedQualityUpdate, this.handleSubscribedQualityUpdate).on(EngineEvent.Closing, this.handleClosing).on(EngineEvent.SignalRequestResponse, this.handleSignalRequestResponse);
27037
27420
  }
27038
27421
  /**
27039
27422
  * Sets and updates the metadata of the local participant.
@@ -28336,76 +28719,23 @@ class Participant extends eventsExports.EventEmitter {
28336
28719
  * @returns A promise that resolves with the response payload or rejects with an error.
28337
28720
  * @throws Error on failure. Details in `message`.
28338
28721
  */
28339
- performRpc(_ref3) {
28340
- let {
28341
- destinationIdentity,
28342
- method,
28343
- payload,
28344
- responseTimeout = 15000
28345
- } = _ref3;
28346
- const maxRoundTripLatency = 7000;
28347
- const minEffectiveTimeout = maxRoundTripLatency + 1000;
28348
- return new TypedPromise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
28349
- var _a, _b, _c, _d;
28350
- if (byteLength(payload) > MAX_PAYLOAD_BYTES) {
28351
- reject(RpcError.builtIn('REQUEST_PAYLOAD_TOO_LARGE'));
28352
- return;
28353
- }
28354
- if (((_b = (_a = this.engine.latestJoinResponse) === null || _a === void 0 ? void 0 : _a.serverInfo) === null || _b === void 0 ? void 0 : _b.version) && compareVersions((_d = (_c = this.engine.latestJoinResponse) === null || _c === void 0 ? void 0 : _c.serverInfo) === null || _d === void 0 ? void 0 : _d.version, '1.8.0') < 0) {
28355
- reject(RpcError.builtIn('UNSUPPORTED_SERVER'));
28356
- return;
28357
- }
28358
- const effectiveTimeout = Math.max(responseTimeout, minEffectiveTimeout);
28359
- const id = crypto.randomUUID();
28360
- yield this.publishRpcRequest(destinationIdentity, id, method, payload, effectiveTimeout);
28361
- const ackTimeoutId = setTimeout(() => {
28362
- this.pendingAcks.delete(id);
28363
- reject(RpcError.builtIn('CONNECTION_TIMEOUT'));
28364
- this.pendingResponses.delete(id);
28365
- clearTimeout(responseTimeoutId);
28366
- }, maxRoundTripLatency);
28367
- this.pendingAcks.set(id, {
28368
- resolve: () => {
28369
- clearTimeout(ackTimeoutId);
28370
- },
28371
- participantIdentity: destinationIdentity
28372
- });
28373
- const responseTimeoutId = setTimeout(() => {
28374
- this.pendingResponses.delete(id);
28375
- reject(RpcError.builtIn('RESPONSE_TIMEOUT'));
28376
- }, responseTimeout);
28377
- this.pendingResponses.set(id, {
28378
- resolve: (responsePayload, responseError) => {
28379
- clearTimeout(responseTimeoutId);
28380
- if (this.pendingAcks.has(id)) {
28381
- this.log.warn('RPC response received before ack', id);
28382
- this.pendingAcks.delete(id);
28383
- clearTimeout(ackTimeoutId);
28384
- }
28385
- if (responseError) {
28386
- reject(responseError);
28387
- } else {
28388
- resolve(responsePayload !== null && responsePayload !== void 0 ? responsePayload : '');
28389
- }
28390
- },
28391
- participantIdentity: destinationIdentity
28392
- });
28393
- }));
28722
+ performRpc(params) {
28723
+ return this.rpcClientManager.performRpc(params).then(_ref3 => {
28724
+ let [_id, completionPromise] = _ref3;
28725
+ return completionPromise;
28726
+ });
28394
28727
  }
28395
28728
  /**
28396
28729
  * @deprecated use `room.registerRpcMethod` instead
28397
28730
  */
28398
28731
  registerRpcMethod(method, handler) {
28399
- if (this.rpcHandlers.has(method)) {
28400
- this.log.warn("you're overriding the RPC handler for method ".concat(method, ", in the future this will throw an error"));
28401
- }
28402
- this.rpcHandlers.set(method, handler);
28732
+ this.rpcServerManager.registerRpcMethod(method, handler);
28403
28733
  }
28404
28734
  /**
28405
28735
  * @deprecated use `room.unregisterRpcMethod` instead
28406
28736
  */
28407
28737
  unregisterRpcMethod(method) {
28408
- this.rpcHandlers.delete(method);
28738
+ this.rpcServerManager.unregisterRpcMethod(method);
28409
28739
  }
28410
28740
  /**
28411
28741
  * Control who can subscribe to LocalParticipant's published tracks.
@@ -28432,63 +28762,6 @@ class Participant extends eventsExports.EventEmitter {
28432
28762
  this.updateTrackSubscriptionPermissions();
28433
28763
  }
28434
28764
  }
28435
- handleIncomingRpcAck(requestId) {
28436
- const handler = this.pendingAcks.get(requestId);
28437
- if (handler) {
28438
- handler.resolve();
28439
- this.pendingAcks.delete(requestId);
28440
- } else {
28441
- console.error('Ack received for unexpected RPC request', requestId);
28442
- }
28443
- }
28444
- handleIncomingRpcResponse(requestId, payload, error) {
28445
- const handler = this.pendingResponses.get(requestId);
28446
- if (handler) {
28447
- handler.resolve(payload, error);
28448
- this.pendingResponses.delete(requestId);
28449
- } else {
28450
- console.error('Response received for unexpected RPC request', requestId);
28451
- }
28452
- }
28453
- /** @internal */
28454
- publishRpcRequest(destinationIdentity, requestId, method, payload, responseTimeout) {
28455
- return __awaiter(this, void 0, void 0, function* () {
28456
- const packet = new DataPacket({
28457
- destinationIdentities: [destinationIdentity],
28458
- kind: DataPacket_Kind.RELIABLE,
28459
- value: {
28460
- case: 'rpcRequest',
28461
- value: new RpcRequest({
28462
- id: requestId,
28463
- method,
28464
- payload,
28465
- responseTimeoutMs: responseTimeout,
28466
- version: 1
28467
- })
28468
- }
28469
- });
28470
- yield this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
28471
- });
28472
- }
28473
- /** @internal */
28474
- handleParticipantDisconnected(participantIdentity) {
28475
- for (const [id, {
28476
- participantIdentity: pendingIdentity
28477
- }] of this.pendingAcks) {
28478
- if (pendingIdentity === participantIdentity) {
28479
- this.pendingAcks.delete(id);
28480
- }
28481
- }
28482
- for (const [id, {
28483
- participantIdentity: pendingIdentity,
28484
- resolve
28485
- }] of this.pendingResponses) {
28486
- if (pendingIdentity === participantIdentity) {
28487
- resolve(null, RpcError.builtIn('RECIPIENT_DISCONNECTED'));
28488
- this.pendingResponses.delete(id);
28489
- }
28490
- }
28491
- }
28492
28765
  /** @internal */
28493
28766
  setEnabledPublishCodecs(codecs) {
28494
28767
  this.enabledPublishVideoCodecs = codecs.filter(c => c.mime.split('/')[0].toLowerCase() === 'video');
@@ -28955,7 +29228,7 @@ class DeferrableMap extends Map {
28955
29228
  return new RemoteDataTrack(info, manager, {
28956
29229
  publisherIdentity: pi.identity
28957
29230
  });
28958
- }));
29231
+ }), pi.clientProtocol);
28959
29232
  }
28960
29233
  get logContext() {
28961
29234
  return Object.assign(Object.assign({}, super.logContext), {
@@ -28967,6 +29240,7 @@ class DeferrableMap extends Map {
28967
29240
  constructor(signalClient, sid, identity, name, metadata, attributes, loggerOptions) {
28968
29241
  let kind = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : ParticipantInfo_Kind.STANDARD;
28969
29242
  let remoteDataTracks = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : [];
29243
+ let clientProtocol = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : CLIENT_PROTOCOL_DEFAULT;
28970
29244
  super(sid, identity || '', name, metadata, attributes, loggerOptions, kind);
28971
29245
  this.signalClient = signalClient;
28972
29246
  this.trackPublications = new Map();
@@ -28976,6 +29250,7 @@ class DeferrableMap extends Map {
28976
29250
  return [remoteDataTrack.info.name, remoteDataTrack];
28977
29251
  }));
28978
29252
  this.volumeMap = new Map();
29253
+ this.clientProtocol = clientProtocol;
28979
29254
  }
28980
29255
  addTrackPublication(publication) {
28981
29256
  super.addTrackPublication(publication);
@@ -29277,7 +29552,6 @@ class Room extends eventsExports.EventEmitter {
29277
29552
  this.log = livekitLogger;
29278
29553
  this.bufferedEvents = [];
29279
29554
  this.isResuming = false;
29280
- this.rpcHandlers = new Map();
29281
29555
  this.connect = (url, token, opts) => __awaiter(this, void 0, void 0, function* () {
29282
29556
  var _a;
29283
29557
  if (!isBrowserSupported()) {
@@ -29834,7 +30108,22 @@ class Room extends eventsExports.EventEmitter {
29834
30108
  this.handleDataStream(packet, encryptionType);
29835
30109
  } else if (packet.value.case === 'rpcRequest') {
29836
30110
  const rpc = packet.value.value;
29837
- this.handleIncomingRpcRequest(packet.participantIdentity, rpc.id, rpc.method, rpc.payload, rpc.responseTimeoutMs, rpc.version);
30111
+ this.rpcServerManager.handleIncomingRpcRequest(packet.participantIdentity, rpc);
30112
+ } else if (packet.value.case === 'rpcResponse') {
30113
+ const rpcResponse = packet.value.value;
30114
+ switch (rpcResponse.value.case) {
30115
+ case 'payload':
30116
+ this.rpcClientManager.handleIncomingRpcResponseSuccess(rpcResponse.requestId, rpcResponse.value.value);
30117
+ break;
30118
+ case 'error':
30119
+ this.rpcClientManager.handleIncomingRpcResponseFailure(rpcResponse.requestId, RpcError.fromProto(rpcResponse.value.value));
30120
+ break;
30121
+ default:
30122
+ this.log.warn("Unknown rpcResponse.value.case: ".concat(rpcResponse.value.case), this.logContext);
30123
+ break;
30124
+ }
30125
+ } else if (packet.value.case === 'rpcAck') {
30126
+ this.rpcClientManager.handleIncomingRpcAck(packet.value.value.requestId);
29838
30127
  }
29839
30128
  };
29840
30129
  this.handleUserPacket = (participant, userPacket, kind, encryptionType) => {
@@ -29926,6 +30215,10 @@ class Room extends eventsExports.EventEmitter {
29926
30215
  }
29927
30216
  });
29928
30217
  };
30218
+ this.getRemoteParticipantClientProtocol = identity => {
30219
+ var _a, _b;
30220
+ return (_b = (_a = this.remoteParticipants.get(identity)) === null || _a === void 0 ? void 0 : _a.clientProtocol) !== null && _b !== void 0 ? _b : CLIENT_PROTOCOL_DEFAULT;
30221
+ };
29929
30222
  this.onLocalParticipantMetadataChanged = metadata => {
29930
30223
  this.emit(RoomEvent.ParticipantMetadataChanged, metadata, this.localParticipant);
29931
30224
  };
@@ -30043,8 +30336,28 @@ class Room extends eventsExports.EventEmitter {
30043
30336
  } = _ref;
30044
30337
  this.engine.sendLossyBytes(bytes, DataChannelKind.DATA_TRACK_LOSSY, 'wait').finally(() => this.outgoingDataTrackManager.handlePacketSendComplete(handle));
30045
30338
  });
30339
+ this.registerRpcDataStreamHandler();
30340
+ this.rpcClientManager = new RpcClientManager(this.log, this.outgoingDataStreamManager, this.getRemoteParticipantClientProtocol, () => {
30341
+ var _a, _b;
30342
+ return (_b = (_a = this.engine.latestJoinResponse) === null || _a === void 0 ? void 0 : _a.serverInfo) === null || _b === void 0 ? void 0 : _b.version;
30343
+ });
30344
+ this.rpcClientManager.on('sendDataPacket', _ref2 => {
30345
+ let {
30346
+ packet
30347
+ } = _ref2;
30348
+ var _a;
30349
+ (_a = this.engine) === null || _a === void 0 ? void 0 : _a.sendDataPacket(packet, DataChannelKind.RELIABLE);
30350
+ });
30351
+ this.rpcServerManager = new RpcServerManager(this.log, this.outgoingDataStreamManager, this.getRemoteParticipantClientProtocol);
30352
+ this.rpcServerManager.on('sendDataPacket', _ref3 => {
30353
+ let {
30354
+ packet
30355
+ } = _ref3;
30356
+ var _a;
30357
+ (_a = this.engine) === null || _a === void 0 ? void 0 : _a.sendDataPacket(packet, DataChannelKind.RELIABLE);
30358
+ });
30046
30359
  this.disconnectLock = new _();
30047
- this.localParticipant = new LocalParticipant('', '', this.engine, this.options, this.rpcHandlers, this.outgoingDataStreamManager, this.outgoingDataTrackManager);
30360
+ this.localParticipant = new LocalParticipant('', '', this.engine, this.options, this.outgoingDataStreamManager, this.outgoingDataTrackManager, this.rpcClientManager, this.rpcServerManager);
30048
30361
  this.setupPacketTrailer();
30049
30362
  if (this.options.e2ee || this.options.encryption) {
30050
30363
  this.setupE2EE();
@@ -30062,16 +30375,32 @@ class Room extends eventsExports.EventEmitter {
30062
30375
  this.switchActiveDevice('audiooutput', unwrapConstraint(this.options.audioOutput.deviceId)).catch(e => this.log.warn("Could not set audio output: ".concat(e.message)));
30063
30376
  }
30064
30377
  if (isWeb()) {
30065
- const abortController = new AbortController();
30066
- // in order to catch device changes prior to room connection we need to register the event in the constructor
30067
- (_f = (_e = navigator.mediaDevices) === null || _e === void 0 ? void 0 : _e.addEventListener) === null || _f === void 0 ? void 0 : _f.call(_e, 'devicechange', this.handleDeviceChange, {
30068
- signal: abortController.signal
30069
- });
30378
+ const cleanupController = new AbortController();
30379
+ let onDeviceChange;
30070
30380
  if (Room.cleanupRegistry) {
30381
+ // Wrap the listener in a WeakRef closure so navigator.mediaDevices does not
30382
+ // strongly retain the Room. When the user drops their Room ref, the
30383
+ // FinalizationRegistry callback aborts the controller and removes the listener.
30384
+ const roomRef = new WeakRef(this);
30385
+ onDeviceChange = () => {
30386
+ const self = roomRef.deref();
30387
+ if (!self) {
30388
+ return;
30389
+ }
30390
+ self.handleDeviceChange();
30391
+ };
30071
30392
  Room.cleanupRegistry.register(this, () => {
30072
- abortController.abort();
30393
+ cleanupController.abort();
30073
30394
  });
30395
+ } else {
30396
+ // Legacy browsers without WeakRef/FinalizationRegistry: fall back to a
30397
+ // direct listener (matches pre-#1944 behavior).
30398
+ onDeviceChange = this.handleDeviceChange;
30074
30399
  }
30400
+ // in order to catch device changes prior to room connection we need to register the event in the constructor
30401
+ (_f = (_e = navigator.mediaDevices) === null || _e === void 0 ? void 0 : _e.addEventListener) === null || _f === void 0 ? void 0 : _f.call(_e, 'devicechange', onDeviceChange, {
30402
+ signal: cleanupController.signal
30403
+ });
30075
30404
  }
30076
30405
  }
30077
30406
  registerTextStreamHandler(topic, callback) {
@@ -30113,10 +30442,7 @@ class Room extends eventsExports.EventEmitter {
30113
30442
  * Other errors thrown in your handler will not be transmitted as-is, and will instead arrive to the caller as `1500` ("Application Error").
30114
30443
  */
30115
30444
  registerRpcMethod(method, handler) {
30116
- if (this.rpcHandlers.has(method)) {
30117
- throw Error("RPC handler already registered for method ".concat(method, ", unregisterRpcMethod before trying to register again"));
30118
- }
30119
- this.rpcHandlers.set(method, handler);
30445
+ this.rpcServerManager.registerRpcMethod(method, handler);
30120
30446
  }
30121
30447
  /**
30122
30448
  * Unregisters a previously registered RPC method.
@@ -30124,7 +30450,7 @@ class Room extends eventsExports.EventEmitter {
30124
30450
  * @param method - The name of the RPC method to unregister
30125
30451
  */
30126
30452
  unregisterRpcMethod(method) {
30127
- this.rpcHandlers.delete(method);
30453
+ this.rpcServerManager.unregisterRpcMethod(method);
30128
30454
  }
30129
30455
  /**
30130
30456
  * @experimental
@@ -30313,8 +30639,8 @@ class Room extends eventsExports.EventEmitter {
30313
30639
  }
30314
30640
  this.outgoingDataTrackManager.receivedSfuUnpublishResponse(event.info.pubHandle);
30315
30641
  }).on(EngineEvent.DataTrackSubscriberHandles, event => {
30316
- const handleToSidMapping = new Map(Object.entries(event.subHandles).map(_ref2 => {
30317
- let [key, value] = _ref2;
30642
+ const handleToSidMapping = new Map(Object.entries(event.subHandles).map(_ref4 => {
30643
+ let [key, value] = _ref4;
30318
30644
  return [parseInt(key, 10), value.trackSid];
30319
30645
  }));
30320
30646
  this.incomingDataTrackManager.receivedSfuSubscriberHandles(handleToSidMapping);
@@ -30768,10 +31094,10 @@ class Room extends eventsExports.EventEmitter {
30768
31094
  }
30769
31095
  }
30770
31096
  handleLocalTrackSubscribed(subscribedSid) {
30771
- const findPublication = () => this.localParticipant.getTrackPublications().find(_ref3 => {
31097
+ const findPublication = () => this.localParticipant.getTrackPublications().find(_ref5 => {
30772
31098
  let {
30773
31099
  trackSid
30774
- } = _ref3;
31100
+ } = _ref5;
30775
31101
  return trackSid === subscribedSid;
30776
31102
  });
30777
31103
  const trackPublication = findPublication();
@@ -30877,7 +31203,6 @@ class Room extends eventsExports.EventEmitter {
30877
31203
  }
30878
31204
  }
30879
31205
  handleParticipantDisconnected(identity, participant) {
30880
- var _a;
30881
31206
  // remove and send event
30882
31207
  this.remoteParticipants.delete(identity);
30883
31208
  if (!participant) {
@@ -30890,45 +31215,7 @@ class Room extends eventsExports.EventEmitter {
30890
31215
  });
30891
31216
  this.emit(RoomEvent.ParticipantDisconnected, participant);
30892
31217
  participant.setDisconnected();
30893
- (_a = this.localParticipant) === null || _a === void 0 ? void 0 : _a.handleParticipantDisconnected(participant.identity);
30894
- }
30895
- handleIncomingRpcRequest(callerIdentity, requestId, method, payload, responseTimeout, version) {
30896
- return __awaiter(this, void 0, void 0, function* () {
30897
- yield this.engine.publishRpcAck(callerIdentity, requestId);
30898
- if (version !== 1) {
30899
- yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn('UNSUPPORTED_VERSION'));
30900
- return;
30901
- }
30902
- const handler = this.rpcHandlers.get(method);
30903
- if (!handler) {
30904
- yield this.engine.publishRpcResponse(callerIdentity, requestId, null, RpcError.builtIn('UNSUPPORTED_METHOD'));
30905
- return;
30906
- }
30907
- let responseError = null;
30908
- let responsePayload = null;
30909
- try {
30910
- const response = yield handler({
30911
- requestId,
30912
- callerIdentity,
30913
- payload,
30914
- responseTimeout
30915
- });
30916
- if (byteLength(response) > MAX_PAYLOAD_BYTES) {
30917
- responseError = RpcError.builtIn('RESPONSE_PAYLOAD_TOO_LARGE');
30918
- this.log.warn("RPC Response payload too large for ".concat(method));
30919
- } else {
30920
- responsePayload = response;
30921
- }
30922
- } catch (error) {
30923
- if (error instanceof RpcError) {
30924
- responseError = error;
30925
- } else {
30926
- this.log.warn("Uncaught error returned by RPC handler for ".concat(method, ". Returning APPLICATION_ERROR instead."), error);
30927
- responseError = RpcError.builtIn('APPLICATION_ERROR');
30928
- }
30929
- }
30930
- yield this.engine.publishRpcResponse(callerIdentity, requestId, responsePayload, responseError);
30931
- });
31218
+ this.rpcClientManager.handleParticipantDisconnected(participant.identity);
30932
31219
  }
30933
31220
  /**
30934
31221
  * attempt to select the default devices if the previously selected devices are no longer available after a device change event
@@ -31134,6 +31421,30 @@ class Room extends eventsExports.EventEmitter {
31134
31421
  return this.remoteParticipants.get(identity);
31135
31422
  }
31136
31423
  }
31424
+ registerRpcDataStreamHandler() {
31425
+ this.incomingDataStreamManager.registerTextStreamHandler(RPC_REQUEST_DATA_STREAM_TOPIC, (reader_1, _a) => __awaiter(this, [reader_1, _a], void 0, function (reader, _ref6) {
31426
+ var _this4 = this;
31427
+ let {
31428
+ identity
31429
+ } = _ref6;
31430
+ return function* () {
31431
+ var _b;
31432
+ const attributes = (_b = reader.info.attributes) !== null && _b !== void 0 ? _b : {};
31433
+ yield _this4.rpcServerManager.handleIncomingDataStream(reader, identity, attributes);
31434
+ }();
31435
+ }));
31436
+ this.incomingDataStreamManager.registerTextStreamHandler(RPC_RESPONSE_DATA_STREAM_TOPIC, (reader_1, _a) => __awaiter(this, [reader_1, _a], void 0, function (reader, _ref7) {
31437
+ var _this5 = this;
31438
+ let {
31439
+ identity
31440
+ } = _ref7;
31441
+ return function* () {
31442
+ var _b;
31443
+ const attributes = (_b = reader.info.attributes) !== null && _b !== void 0 ? _b : {};
31444
+ yield _this5.rpcClientManager.handleIncomingDataStream(reader, identity, attributes);
31445
+ }();
31446
+ }));
31447
+ }
31137
31448
  registerConnectionReconcile() {
31138
31449
  this.clearConnectionReconcile();
31139
31450
  let consecutiveFailures = 0;
@@ -31179,8 +31490,8 @@ class Room extends eventsExports.EventEmitter {
31179
31490
  return true;
31180
31491
  }
31181
31492
  emitBufferedEvents() {
31182
- this.bufferedEvents.forEach(_ref4 => {
31183
- let [ev, args] = _ref4;
31493
+ this.bufferedEvents.forEach(_ref8 => {
31494
+ let [ev, args] = _ref8;
31184
31495
  this.emit(ev, ...args);
31185
31496
  });
31186
31497
  this.bufferedEvents = [];
@@ -31331,7 +31642,7 @@ class Room extends eventsExports.EventEmitter {
31331
31642
  return super.emit(event, ...args);
31332
31643
  }
31333
31644
  }
31334
- Room.cleanupRegistry = typeof FinalizationRegistry !== 'undefined' && new FinalizationRegistry(cleanup => {
31645
+ Room.cleanupRegistry = typeof FinalizationRegistry !== 'undefined' && typeof WeakRef !== 'undefined' && new FinalizationRegistry(cleanup => {
31335
31646
  cleanup();
31336
31647
  });
31337
31648
  function mapArgs(args) {
@@ -32766,4 +33077,4 @@ const serializers = {
32766
33077
  json,
32767
33078
  raw,
32768
33079
  custom
32769
- };export{AudioPresets,BackupCodecPolicy,BaseKeyProvider,CheckStatus,Checker,ConnectionCheck,ConnectionError,ConnectionErrorReason,ConnectionQuality,ConnectionState,CriticalTimers,CryptorError,CryptorErrorReason,CryptorEvent,DataPacket_Kind,DataStreamError,DataStreamErrorReason,DataTrackPacket,DefaultReconnectPolicy,DeviceUnsupportedError,DisconnectReason,EncryptionEvent,Encryption_Type,EngineEvent,ExternalE2EEKeyProvider,KeyHandlerEvent,KeyProviderEvent,LivekitError,LivekitReasonedError,LocalAudioTrack,LocalDataTrack,LocalParticipant,LocalTrack,LocalTrackPublication,LocalTrackRecorder,LocalVideoTrack,LogLevel,LoggerNames,MediaDeviceFailure,_ as Mutex,NegotiationError,PacketTrailerManager,Participant,ParticipantEvent,ParticipantInfo_Kind as ParticipantKind,PublishDataError,PublishTrackError,RemoteAudioTrack,RemoteDataTrack,RemoteParticipant,RemoteTrack,RemoteTrackPublication,RemoteVideoTrack,Room,RoomEvent,RpcError,ScreenSharePresets,SignalReconnectError,SignalRequestError,SimulatedError,SubscriptionError,TokenSource,TokenSourceConfigurable,TokenSourceFixed,Track,TrackEvent,TrackInvalidError,TrackPublication,TrackType,UnexpectedConnectionState,UnsupportedServer,VideoPreset,VideoPresets,VideoPresets43,VideoQuality,areTokenSourceFetchOptionsEqual,asEncryptablePacket,attachToElement,attributeTypings as attributes,audioCodecs,compareVersions,createAudioAnalyser,createE2EEKey,createKeyMaterialFromBuffer,createKeyMaterialFromString,createLocalAudioTrack,createLocalScreenTracks,createLocalTracks,createLocalVideoTrack,decodeTokenPayload,deriveKeys,detachTrack,facingModeFromDeviceLabel,facingModeFromLocalTrack,getBrowser,getEmptyAudioStreamTrack,getEmptyVideoStreamTrack,getLogger,importKey,isAudioCodec,isAudioTrack,isBackupCodec,isBackupVideoCodec,isBrowserSupported,isE2EESupported,isInsertableStreamSupported,isLocalParticipant,isLocalTrack,isRemoteParticipant,isRemoteTrack,isScriptTransformSupported,isSerializer,isVideoCodec,isVideoFrame,isVideoTrack,needsRbspUnescaping,parseRbsp,protocolVersion,ratchet,serializers,setLogExtension,setLogLevel,supportsAV1,supportsAdaptiveStream,supportsAudioOutputSelection,supportsDynacast,supportsVP9,version,videoCodecs,writeRbsp};//# sourceMappingURL=livekit-client.esm.mjs.map
33080
+ };export{AudioPresets,BackupCodecPolicy,BaseKeyProvider,CLIENT_PROTOCOL_DATA_STREAM_RPC,CLIENT_PROTOCOL_DEFAULT,CheckStatus,Checker,ConnectionCheck,ConnectionError,ConnectionErrorReason,ConnectionQuality,ConnectionState,CriticalTimers,CryptorError,CryptorErrorReason,CryptorEvent,DataPacket_Kind,DataStreamError,DataStreamErrorReason,DataTrackPacket,DefaultReconnectPolicy,DeviceUnsupportedError,DisconnectReason,EncryptionEvent,Encryption_Type,EngineEvent,ExternalE2EEKeyProvider,KeyHandlerEvent,KeyProviderEvent,LivekitError,LivekitReasonedError,LocalAudioTrack,LocalDataTrack,LocalParticipant,LocalTrack,LocalTrackPublication,LocalTrackRecorder,LocalVideoTrack,LogLevel,LoggerNames,MediaDeviceFailure,_ as Mutex,NegotiationError,PacketTrailerManager,Participant,ParticipantEvent,ParticipantInfo_Kind as ParticipantKind,PublishDataError,PublishTrackError,RemoteAudioTrack,RemoteDataTrack,RemoteParticipant,RemoteTrack,RemoteTrackPublication,RemoteVideoTrack,Room,RoomEvent,RpcError,ScreenSharePresets,SignalReconnectError,SignalRequestError,SimulatedError,SubscriptionError,TokenSource,TokenSourceConfigurable,TokenSourceFixed,Track,TrackEvent,TrackInvalidError,TrackPublication,TrackType,UnexpectedConnectionState,UnsupportedServer,VideoPreset,VideoPresets,VideoPresets43,VideoQuality,areTokenSourceFetchOptionsEqual,asEncryptablePacket,attachToElement,attributeTypings as attributes,audioCodecs,clientProtocol,compareVersions,createAudioAnalyser,createE2EEKey,createKeyMaterialFromBuffer,createKeyMaterialFromString,createLocalAudioTrack,createLocalScreenTracks,createLocalTracks,createLocalVideoTrack,decodeTokenPayload,deriveKeys,detachTrack,facingModeFromDeviceLabel,facingModeFromLocalTrack,getBrowser,getEmptyAudioStreamTrack,getEmptyVideoStreamTrack,getLogger,importKey,isAudioCodec,isAudioTrack,isBackupCodec,isBackupVideoCodec,isBrowserSupported,isE2EESupported,isInsertableStreamSupported,isLocalParticipant,isLocalTrack,isRemoteParticipant,isRemoteTrack,isScriptTransformSupported,isSerializer,isVideoCodec,isVideoFrame,isVideoTrack,needsRbspUnescaping,parseRbsp,protocolVersion,ratchet,serializers,setLogExtension,setLogLevel,supportsAV1,supportsAdaptiveStream,supportsAudioOutputSelection,supportsDynacast,supportsVP9,version,videoCodecs,writeRbsp};//# sourceMappingURL=livekit-client.esm.mjs.map