livekit-client 2.18.10 → 2.19.0
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.
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +720 -430
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.pt.worker.js.map +1 -1
- package/dist/livekit-client.pt.worker.mjs.map +1 -1
- package/dist/livekit-client.umd.js +1 -1
- package/dist/livekit-client.umd.js.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +0 -3
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +4 -2
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +5 -13
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts +5 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
- package/dist/src/room/rpc/client/RpcClientManager.d.ts +39 -0
- package/dist/src/room/rpc/client/RpcClientManager.d.ts.map +1 -0
- package/dist/src/room/rpc/client/events.d.ts +8 -0
- package/dist/src/room/rpc/client/events.d.ts.map +1 -0
- package/dist/src/room/rpc/index.d.ts +6 -0
- package/dist/src/room/rpc/index.d.ts.map +1 -0
- package/dist/src/room/rpc/server/RpcServerManager.d.ts +44 -0
- package/dist/src/room/rpc/server/RpcServerManager.d.ts.map +1 -0
- package/dist/src/room/rpc/server/events.d.ts +8 -0
- package/dist/src/room/rpc/server/events.d.ts.map +1 -0
- package/dist/src/room/{rpc.d.ts → rpc/utils.d.ts} +34 -4
- package/dist/src/room/rpc/utils.d.ts.map +1 -0
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/src/version.d.ts +8 -0
- package/dist/src/version.d.ts.map +1 -1
- package/dist/ts4.2/room/RTCEngine.d.ts +0 -3
- package/dist/ts4.2/room/Room.d.ts +4 -2
- package/dist/ts4.2/room/participant/LocalParticipant.d.ts +5 -13
- package/dist/ts4.2/room/participant/RemoteParticipant.d.ts +5 -1
- package/dist/ts4.2/room/rpc/client/RpcClientManager.d.ts +43 -0
- package/dist/ts4.2/room/rpc/client/events.d.ts +8 -0
- package/dist/ts4.2/room/rpc/index.d.ts +7 -0
- package/dist/ts4.2/room/rpc/server/RpcServerManager.d.ts +44 -0
- package/dist/ts4.2/room/rpc/server/events.d.ts +8 -0
- package/dist/ts4.2/room/{rpc.d.ts → rpc/utils.d.ts} +34 -4
- package/dist/ts4.2/version.d.ts +8 -0
- package/package.json +1 -1
- package/src/room/RTCEngine.ts +0 -26
- package/src/room/Room.ts +83 -81
- package/src/room/participant/LocalParticipant.ts +16 -180
- package/src/room/participant/RemoteParticipant.ts +9 -0
- package/src/room/rpc/client/RpcClientManager.test.ts +430 -0
- package/src/room/rpc/client/RpcClientManager.ts +269 -0
- package/src/room/rpc/client/events.ts +9 -0
- package/src/room/rpc/index.ts +14 -0
- package/src/room/rpc/server/RpcServerManager.test.ts +471 -0
- package/src/room/rpc/server/RpcServerManager.ts +293 -0
- package/src/room/rpc/server/events.ts +9 -0
- package/src/room/{rpc.ts → rpc/utils.ts} +49 -8
- package/src/room/utils.ts +2 -1
- package/src/version.ts +10 -0
- package/dist/src/room/rpc.d.ts.map +0 -1
- 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.
|
|
11796
|
-
const protocolVersion = 17
|
|
11796
|
+
}var version$1 = "2.19.0";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()) {
|
|
@@ -18970,118 +18980,6 @@ class PCTransportManager {
|
|
|
18970
18980
|
}();
|
|
18971
18981
|
});
|
|
18972
18982
|
}
|
|
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
18983
|
}// Check if MediaRecorder is available
|
|
19086
18984
|
const isMediaRecorderAvailable = typeof MediaRecorder !== 'undefined';
|
|
19087
18985
|
// Fallback class for environments without MediaRecorder
|
|
@@ -22296,29 +22194,6 @@ class RTCEngine extends eventsExports.EventEmitter {
|
|
|
22296
22194
|
});
|
|
22297
22195
|
}
|
|
22298
22196
|
/** @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
22197
|
publishRpcAck(destinationIdentity, requestId) {
|
|
22323
22198
|
return __awaiter(this, void 0, void 0, function* () {
|
|
22324
22199
|
const packet = new DataPacket({
|
|
@@ -25863,113 +25738,636 @@ class OutgoingDataTrackManager extends eventsExports.EventEmitter {
|
|
|
25863
25738
|
this.emit('reset');
|
|
25864
25739
|
});
|
|
25865
25740
|
}
|
|
25866
|
-
}
|
|
25867
|
-
|
|
25868
|
-
|
|
25869
|
-
|
|
25870
|
-
|
|
25871
|
-
|
|
25872
|
-
|
|
25873
|
-
|
|
25874
|
-
|
|
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
|
-
}
|
|
25741
|
+
}/**
|
|
25742
|
+
* Specialized error handling for RPC methods.
|
|
25743
|
+
*
|
|
25744
|
+
* Instances of this type, when thrown in a method handler, will have their `message`
|
|
25745
|
+
* serialized and sent across the wire. The sender will receive an equivalent error on the other side.
|
|
25746
|
+
*
|
|
25747
|
+
* Built-in types are included but developers may use any string, with a max length of 256 bytes.
|
|
25748
|
+
*/
|
|
25749
|
+
class RpcError extends Error {
|
|
25886
25750
|
/**
|
|
25887
|
-
*
|
|
25751
|
+
* Creates an error object with the given code and message, plus an optional data payload.
|
|
25752
|
+
*
|
|
25753
|
+
* If thrown in an RPC method handler, the error will be sent back to the caller.
|
|
25754
|
+
*
|
|
25755
|
+
* Error codes 1001-1999 are reserved for built-in errors (see RpcError.ErrorCode for their meanings).
|
|
25888
25756
|
*/
|
|
25889
|
-
|
|
25890
|
-
|
|
25891
|
-
|
|
25892
|
-
|
|
25893
|
-
|
|
25894
|
-
|
|
25895
|
-
|
|
25896
|
-
}
|
|
25897
|
-
}
|
|
25898
|
-
if (isReactNative()) {
|
|
25899
|
-
// @ts-ignore
|
|
25900
|
-
this._mediaStreamTrack._setVolume(volume);
|
|
25757
|
+
constructor(code, message, data, options) {
|
|
25758
|
+
super(message);
|
|
25759
|
+
this.code = code;
|
|
25760
|
+
this.message = truncateBytes(message, RpcError.MAX_MESSAGE_BYTES);
|
|
25761
|
+
this.data = data ? truncateBytes(data, RpcError.MAX_DATA_BYTES) : undefined;
|
|
25762
|
+
if (typeof (options === null || options === void 0 ? void 0 : options.cause) !== 'undefined') {
|
|
25763
|
+
this.cause = options === null || options === void 0 ? void 0 : options.cause;
|
|
25901
25764
|
}
|
|
25902
|
-
this.elementVolume = volume;
|
|
25903
25765
|
}
|
|
25904
25766
|
/**
|
|
25905
|
-
*
|
|
25767
|
+
* @internal
|
|
25906
25768
|
*/
|
|
25907
|
-
|
|
25908
|
-
|
|
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;
|
|
25769
|
+
static fromProto(proto) {
|
|
25770
|
+
return new RpcError(proto.code, proto.message, proto.data);
|
|
25922
25771
|
}
|
|
25923
25772
|
/**
|
|
25924
|
-
*
|
|
25925
|
-
* @param deviceId audio output device
|
|
25773
|
+
* @internal
|
|
25926
25774
|
*/
|
|
25927
|
-
|
|
25928
|
-
return
|
|
25929
|
-
this.
|
|
25930
|
-
|
|
25931
|
-
|
|
25932
|
-
return;
|
|
25933
|
-
}
|
|
25934
|
-
/* @ts-ignore */
|
|
25935
|
-
return elm.setSinkId(deviceId);
|
|
25936
|
-
}));
|
|
25775
|
+
toProto() {
|
|
25776
|
+
return new RpcError$1({
|
|
25777
|
+
code: this.code,
|
|
25778
|
+
message: this.message,
|
|
25779
|
+
data: this.data
|
|
25937
25780
|
});
|
|
25938
25781
|
}
|
|
25939
|
-
|
|
25940
|
-
|
|
25941
|
-
|
|
25942
|
-
|
|
25943
|
-
|
|
25944
|
-
|
|
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;
|
|
25782
|
+
/**
|
|
25783
|
+
* Creates an error object from the code, with an auto-populated message.
|
|
25784
|
+
*
|
|
25785
|
+
* @internal
|
|
25786
|
+
*/
|
|
25787
|
+
static builtIn(key, data, options) {
|
|
25788
|
+
return new RpcError(RpcError.ErrorCode[key], RpcError.ErrorMessage[key], data, options);
|
|
25962
25789
|
}
|
|
25963
|
-
|
|
25964
|
-
|
|
25965
|
-
|
|
25966
|
-
|
|
25967
|
-
|
|
25968
|
-
|
|
25969
|
-
|
|
25970
|
-
|
|
25971
|
-
|
|
25972
|
-
|
|
25790
|
+
}
|
|
25791
|
+
RpcError.MAX_MESSAGE_BYTES = 256;
|
|
25792
|
+
RpcError.MAX_DATA_BYTES = 15360; // 15 KB
|
|
25793
|
+
RpcError.ErrorCode = {
|
|
25794
|
+
APPLICATION_ERROR: 1500,
|
|
25795
|
+
CONNECTION_TIMEOUT: 1501,
|
|
25796
|
+
RESPONSE_TIMEOUT: 1502,
|
|
25797
|
+
RECIPIENT_DISCONNECTED: 1503,
|
|
25798
|
+
RESPONSE_PAYLOAD_TOO_LARGE: 1504,
|
|
25799
|
+
SEND_FAILED: 1505,
|
|
25800
|
+
UNSUPPORTED_METHOD: 1400,
|
|
25801
|
+
RECIPIENT_NOT_FOUND: 1401,
|
|
25802
|
+
REQUEST_PAYLOAD_TOO_LARGE: 1402,
|
|
25803
|
+
UNSUPPORTED_SERVER: 1403,
|
|
25804
|
+
UNSUPPORTED_VERSION: 1404
|
|
25805
|
+
};
|
|
25806
|
+
/**
|
|
25807
|
+
* @internal
|
|
25808
|
+
*/
|
|
25809
|
+
RpcError.ErrorMessage = {
|
|
25810
|
+
APPLICATION_ERROR: 'Application error in method handler',
|
|
25811
|
+
CONNECTION_TIMEOUT: 'Connection timeout',
|
|
25812
|
+
RESPONSE_TIMEOUT: 'Response timeout',
|
|
25813
|
+
RECIPIENT_DISCONNECTED: 'Recipient disconnected',
|
|
25814
|
+
RESPONSE_PAYLOAD_TOO_LARGE: 'Response payload too large',
|
|
25815
|
+
SEND_FAILED: 'Failed to send',
|
|
25816
|
+
UNSUPPORTED_METHOD: 'Method not supported at destination',
|
|
25817
|
+
RECIPIENT_NOT_FOUND: 'Recipient not found',
|
|
25818
|
+
REQUEST_PAYLOAD_TOO_LARGE: 'Request payload too large',
|
|
25819
|
+
UNSUPPORTED_SERVER: 'RPC not supported by server',
|
|
25820
|
+
UNSUPPORTED_VERSION: 'Unsupported RPC version'
|
|
25821
|
+
};
|
|
25822
|
+
/*
|
|
25823
|
+
* Maximum payload size for RPC requests and responses for clients with a clientProtocol of less
|
|
25824
|
+
* than CLIENT_PROTOCOL_DATA_STREAM_RPC.
|
|
25825
|
+
*
|
|
25826
|
+
* If a payload exceeds this size and the remote client does not support compression,
|
|
25827
|
+
* the RPC call will fail with a REQUEST_PAYLOAD_TOO_LARGE(1402) or RESPONSE_PAYLOAD_TOO_LARGE(1504) error.
|
|
25828
|
+
*/
|
|
25829
|
+
const MAX_V1_PAYLOAD_BYTES = 15360; // 15 KB
|
|
25830
|
+
/**
|
|
25831
|
+
* Topic used for v2 RPC request data streams.
|
|
25832
|
+
* @internal
|
|
25833
|
+
*/
|
|
25834
|
+
const RPC_REQUEST_DATA_STREAM_TOPIC = 'lk.rpc_request';
|
|
25835
|
+
/**
|
|
25836
|
+
* Topic used for v2 RPC response data streams.
|
|
25837
|
+
* @internal
|
|
25838
|
+
*/
|
|
25839
|
+
const RPC_RESPONSE_DATA_STREAM_TOPIC = 'lk.rpc_response';
|
|
25840
|
+
/** @internal */
|
|
25841
|
+
var RpcRequestAttrs;
|
|
25842
|
+
(function (RpcRequestAttrs) {
|
|
25843
|
+
RpcRequestAttrs["RPC_REQUEST_ID"] = "lk.rpc_request_id";
|
|
25844
|
+
RpcRequestAttrs["RPC_REQUEST_METHOD"] = "lk.rpc_request_method";
|
|
25845
|
+
RpcRequestAttrs["RPC_REQUEST_RESPONSE_TIMEOUT_MS"] = "lk.rpc_request_response_timeout_ms";
|
|
25846
|
+
RpcRequestAttrs["RPC_REQUEST_VERSION"] = "lk.rpc_request_version";
|
|
25847
|
+
})(RpcRequestAttrs || (RpcRequestAttrs = {}));
|
|
25848
|
+
/** Initial version of rpc which uses RpcRequest / RpcResponse messages.
|
|
25849
|
+
* @internal
|
|
25850
|
+
**/
|
|
25851
|
+
const RPC_VERSION_V1 = 1;
|
|
25852
|
+
/** Rpc version backed by data streams instead of RpcRequest / RpcResponse.
|
|
25853
|
+
* @internal
|
|
25854
|
+
**/
|
|
25855
|
+
const RPC_VERSION_V2 = 2;
|
|
25856
|
+
/**
|
|
25857
|
+
* @internal
|
|
25858
|
+
*/
|
|
25859
|
+
function byteLength(str) {
|
|
25860
|
+
const encoder = new TextEncoder();
|
|
25861
|
+
return encoder.encode(str).length;
|
|
25862
|
+
}
|
|
25863
|
+
/**
|
|
25864
|
+
* @internal
|
|
25865
|
+
*/
|
|
25866
|
+
function truncateBytes(str, maxBytes) {
|
|
25867
|
+
if (byteLength(str) <= maxBytes) {
|
|
25868
|
+
return str;
|
|
25869
|
+
}
|
|
25870
|
+
let low = 0;
|
|
25871
|
+
let high = str.length;
|
|
25872
|
+
const encoder = new TextEncoder();
|
|
25873
|
+
while (low < high) {
|
|
25874
|
+
const mid = Math.floor((low + high + 1) / 2);
|
|
25875
|
+
if (encoder.encode(str.slice(0, mid)).length <= maxBytes) {
|
|
25876
|
+
low = mid;
|
|
25877
|
+
} else {
|
|
25878
|
+
high = mid - 1;
|
|
25879
|
+
}
|
|
25880
|
+
}
|
|
25881
|
+
return str.slice(0, low);
|
|
25882
|
+
}/**
|
|
25883
|
+
* Manages the client (caller) side of RPC: sending requests, tracking pending
|
|
25884
|
+
* ack/response state, and handling incoming ack/response packets.
|
|
25885
|
+
* @internal
|
|
25886
|
+
*/
|
|
25887
|
+
class RpcClientManager extends EventEmitter {
|
|
25888
|
+
constructor(log, outgoingDataStreamManager, getRemoteParticipantClientProtocol, getServerVersion) {
|
|
25889
|
+
super();
|
|
25890
|
+
this.pendingAcks = new Map();
|
|
25891
|
+
this.pendingResponses = new Map();
|
|
25892
|
+
this.log = log;
|
|
25893
|
+
this.outgoingDataStreamManager = outgoingDataStreamManager;
|
|
25894
|
+
this.getRemoteParticipantClientProtocol = getRemoteParticipantClientProtocol;
|
|
25895
|
+
this.getServerVersion = getServerVersion;
|
|
25896
|
+
}
|
|
25897
|
+
performRpc(_a) {
|
|
25898
|
+
return __awaiter(this, arguments, void 0, function (_ref) {
|
|
25899
|
+
var _this = this;
|
|
25900
|
+
let {
|
|
25901
|
+
destinationIdentity,
|
|
25902
|
+
method,
|
|
25903
|
+
payload,
|
|
25904
|
+
responseTimeout: responseTimeoutMs = 15000
|
|
25905
|
+
} = _ref;
|
|
25906
|
+
return function* () {
|
|
25907
|
+
const maxRoundTripLatencyMs = 7000;
|
|
25908
|
+
const minEffectiveTimeoutMs = maxRoundTripLatencyMs + 1000;
|
|
25909
|
+
const remoteClientProtocol = _this.getRemoteParticipantClientProtocol(destinationIdentity);
|
|
25910
|
+
const payloadBytes = byteLength(payload);
|
|
25911
|
+
// Only enforce the legacy size limit when on rpc v1
|
|
25912
|
+
if (payloadBytes > MAX_V1_PAYLOAD_BYTES && remoteClientProtocol < CLIENT_PROTOCOL_DATA_STREAM_RPC) {
|
|
25913
|
+
throw RpcError.builtIn('REQUEST_PAYLOAD_TOO_LARGE');
|
|
25914
|
+
}
|
|
25915
|
+
const serverVersion = _this.getServerVersion();
|
|
25916
|
+
if (serverVersion && compareVersions(serverVersion, '1.8.0') < 0) {
|
|
25917
|
+
throw RpcError.builtIn('UNSUPPORTED_SERVER');
|
|
25918
|
+
}
|
|
25919
|
+
const effectiveTimeoutMs = Math.max(responseTimeoutMs, minEffectiveTimeoutMs);
|
|
25920
|
+
const id = crypto.randomUUID();
|
|
25921
|
+
const completionFuture = new Future();
|
|
25922
|
+
const ackTimeoutId = setTimeout(() => {
|
|
25923
|
+
var _a;
|
|
25924
|
+
_this.pendingAcks.delete(id);
|
|
25925
|
+
(_a = completionFuture.reject) === null || _a === void 0 ? void 0 : _a.call(completionFuture, RpcError.builtIn('CONNECTION_TIMEOUT'));
|
|
25926
|
+
_this.pendingResponses.delete(id);
|
|
25927
|
+
clearTimeout(responseTimeoutId);
|
|
25928
|
+
}, maxRoundTripLatencyMs);
|
|
25929
|
+
_this.pendingAcks.set(id, {
|
|
25930
|
+
resolve: () => {
|
|
25931
|
+
clearTimeout(ackTimeoutId);
|
|
25932
|
+
},
|
|
25933
|
+
participantIdentity: destinationIdentity
|
|
25934
|
+
});
|
|
25935
|
+
_this.pendingResponses.set(id, {
|
|
25936
|
+
completionFuture,
|
|
25937
|
+
participantIdentity: destinationIdentity
|
|
25938
|
+
});
|
|
25939
|
+
yield _this.publishRpcRequest(destinationIdentity, id, method, payload, effectiveTimeoutMs, remoteClientProtocol);
|
|
25940
|
+
const responseTimeoutId = setTimeout(() => {
|
|
25941
|
+
var _a;
|
|
25942
|
+
_this.pendingResponses.delete(id);
|
|
25943
|
+
(_a = completionFuture.reject) === null || _a === void 0 ? void 0 : _a.call(completionFuture, RpcError.builtIn('RESPONSE_TIMEOUT'));
|
|
25944
|
+
}, responseTimeoutMs);
|
|
25945
|
+
const completionPromise = completionFuture.promise.finally(() => {
|
|
25946
|
+
clearTimeout(responseTimeoutId);
|
|
25947
|
+
if (_this.pendingAcks.has(id)) {
|
|
25948
|
+
_this.log.warn('RPC response received before ack', id);
|
|
25949
|
+
_this.pendingAcks.delete(id);
|
|
25950
|
+
clearTimeout(ackTimeoutId);
|
|
25951
|
+
}
|
|
25952
|
+
});
|
|
25953
|
+
return [id, completionPromise];
|
|
25954
|
+
}();
|
|
25955
|
+
});
|
|
25956
|
+
}
|
|
25957
|
+
publishRpcRequest(destinationIdentity, requestId, method, payload, responseTimeout, remoteClientProtocol) {
|
|
25958
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25959
|
+
if (remoteClientProtocol >= CLIENT_PROTOCOL_DATA_STREAM_RPC) {
|
|
25960
|
+
// Send payload as a data stream - a "version 2" rpc request.
|
|
25961
|
+
const writer = yield this.outgoingDataStreamManager.streamText({
|
|
25962
|
+
topic: RPC_REQUEST_DATA_STREAM_TOPIC,
|
|
25963
|
+
destinationIdentities: [destinationIdentity],
|
|
25964
|
+
attributes: {
|
|
25965
|
+
[RpcRequestAttrs.RPC_REQUEST_ID]: requestId,
|
|
25966
|
+
[RpcRequestAttrs.RPC_REQUEST_METHOD]: method,
|
|
25967
|
+
[RpcRequestAttrs.RPC_REQUEST_RESPONSE_TIMEOUT_MS]: "".concat(responseTimeout),
|
|
25968
|
+
[RpcRequestAttrs.RPC_REQUEST_VERSION]: "".concat(RPC_VERSION_V2)
|
|
25969
|
+
}
|
|
25970
|
+
});
|
|
25971
|
+
yield writer.write(payload);
|
|
25972
|
+
yield writer.close();
|
|
25973
|
+
return;
|
|
25974
|
+
}
|
|
25975
|
+
// Fallback to sending a literal RpcRequest - a "version 1" rpc request.
|
|
25976
|
+
this.emit('sendDataPacket', {
|
|
25977
|
+
packet: new DataPacket({
|
|
25978
|
+
destinationIdentities: [destinationIdentity],
|
|
25979
|
+
kind: DataPacket_Kind.RELIABLE,
|
|
25980
|
+
value: {
|
|
25981
|
+
case: 'rpcRequest',
|
|
25982
|
+
value: new RpcRequest({
|
|
25983
|
+
id: requestId,
|
|
25984
|
+
method,
|
|
25985
|
+
payload,
|
|
25986
|
+
responseTimeoutMs: responseTimeout,
|
|
25987
|
+
version: RPC_VERSION_V1
|
|
25988
|
+
})
|
|
25989
|
+
}
|
|
25990
|
+
})
|
|
25991
|
+
});
|
|
25992
|
+
});
|
|
25993
|
+
}
|
|
25994
|
+
/**
|
|
25995
|
+
* Handle an incoming data stream containing an RPC response payload.
|
|
25996
|
+
* @internal
|
|
25997
|
+
*/
|
|
25998
|
+
handleIncomingDataStream(reader, senderIdentity, attributes) {
|
|
25999
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26000
|
+
const associatedRequestId = attributes[RpcRequestAttrs.RPC_REQUEST_ID];
|
|
26001
|
+
if (!associatedRequestId) {
|
|
26002
|
+
this.log.warn("RPC data stream malformed: ".concat(RpcRequestAttrs.RPC_REQUEST_ID, " not set."));
|
|
26003
|
+
// NOTE: no response can be sent here, because there's no request id so associate
|
|
26004
|
+
// so logging is the best we can do here.
|
|
26005
|
+
return;
|
|
26006
|
+
}
|
|
26007
|
+
const pending = this.pendingResponses.get(associatedRequestId);
|
|
26008
|
+
if (pending && pending.participantIdentity !== senderIdentity) {
|
|
26009
|
+
this.log.warn("RPC response stream for ".concat(associatedRequestId, " arrived from unexpected sender ").concat(senderIdentity, ", expected ").concat(pending.participantIdentity, ". Ignoring."));
|
|
26010
|
+
return;
|
|
26011
|
+
}
|
|
26012
|
+
let payload;
|
|
26013
|
+
try {
|
|
26014
|
+
payload = yield reader.readAll();
|
|
26015
|
+
} catch (e) {
|
|
26016
|
+
this.log.warn("Error reading RPC response payload: ".concat(e));
|
|
26017
|
+
this.handleIncomingRpcResponseFailure(associatedRequestId, RpcError.builtIn('APPLICATION_ERROR', 'Error reading RPC response payload', {
|
|
26018
|
+
cause: e
|
|
26019
|
+
}));
|
|
26020
|
+
return;
|
|
26021
|
+
}
|
|
26022
|
+
this.handleIncomingRpcResponseSuccess(associatedRequestId, payload);
|
|
26023
|
+
});
|
|
26024
|
+
}
|
|
26025
|
+
/** @internal */
|
|
26026
|
+
handleIncomingRpcResponseSuccess(requestId, payload) {
|
|
26027
|
+
var _a, _b;
|
|
26028
|
+
const handler = this.pendingResponses.get(requestId);
|
|
26029
|
+
if (handler) {
|
|
26030
|
+
(_b = (_a = handler.completionFuture).resolve) === null || _b === void 0 ? void 0 : _b.call(_a, payload);
|
|
26031
|
+
this.pendingResponses.delete(requestId);
|
|
26032
|
+
} else {
|
|
26033
|
+
this.log.error('Response received for unexpected RPC request', requestId);
|
|
26034
|
+
}
|
|
26035
|
+
}
|
|
26036
|
+
/** @internal */
|
|
26037
|
+
handleIncomingRpcResponseFailure(requestId, error) {
|
|
26038
|
+
var _a, _b;
|
|
26039
|
+
const handler = this.pendingResponses.get(requestId);
|
|
26040
|
+
if (handler) {
|
|
26041
|
+
(_b = (_a = handler.completionFuture).reject) === null || _b === void 0 ? void 0 : _b.call(_a, error);
|
|
26042
|
+
this.pendingResponses.delete(requestId);
|
|
26043
|
+
} else {
|
|
26044
|
+
this.log.error('Response received for unexpected RPC request', requestId);
|
|
26045
|
+
}
|
|
26046
|
+
}
|
|
26047
|
+
/** @internal */
|
|
26048
|
+
handleIncomingRpcAck(requestId) {
|
|
26049
|
+
const handler = this.pendingAcks.get(requestId);
|
|
26050
|
+
if (handler) {
|
|
26051
|
+
handler.resolve();
|
|
26052
|
+
this.pendingAcks.delete(requestId);
|
|
26053
|
+
} else {
|
|
26054
|
+
this.log.error("Ack received for unexpected RPC request: ".concat(requestId));
|
|
26055
|
+
}
|
|
26056
|
+
}
|
|
26057
|
+
/** @internal */
|
|
26058
|
+
handleParticipantDisconnected(participantIdentity) {
|
|
26059
|
+
var _a;
|
|
26060
|
+
for (const [id, {
|
|
26061
|
+
participantIdentity: pendingIdentity
|
|
26062
|
+
}] of this.pendingAcks) {
|
|
26063
|
+
if (pendingIdentity === participantIdentity) {
|
|
26064
|
+
this.pendingAcks.delete(id);
|
|
26065
|
+
}
|
|
26066
|
+
}
|
|
26067
|
+
for (const [id, {
|
|
26068
|
+
participantIdentity: pendingIdentity,
|
|
26069
|
+
completionFuture
|
|
26070
|
+
}] of this.pendingResponses) {
|
|
26071
|
+
if (pendingIdentity === participantIdentity) {
|
|
26072
|
+
(_a = completionFuture.reject) === null || _a === void 0 ? void 0 : _a.call(completionFuture, RpcError.builtIn('RECIPIENT_DISCONNECTED'));
|
|
26073
|
+
this.pendingResponses.delete(id);
|
|
26074
|
+
}
|
|
26075
|
+
}
|
|
26076
|
+
}
|
|
26077
|
+
}/**
|
|
26078
|
+
* Manages the server (handler) side of RPC: processing incoming requests,
|
|
26079
|
+
* managing registered method handlers, and sending responses.
|
|
26080
|
+
* @internal
|
|
26081
|
+
*/
|
|
26082
|
+
class RpcServerManager extends EventEmitter {
|
|
26083
|
+
constructor(log, outgoingDataStreamManager, getRemoteParticipantClientProtocol) {
|
|
26084
|
+
super();
|
|
26085
|
+
this.rpcHandlers = new Map();
|
|
26086
|
+
this.log = log;
|
|
26087
|
+
this.outgoingDataStreamManager = outgoingDataStreamManager;
|
|
26088
|
+
this.getRemoteParticipantClientProtocol = getRemoteParticipantClientProtocol;
|
|
26089
|
+
}
|
|
26090
|
+
registerRpcMethod(method, handler) {
|
|
26091
|
+
if (this.rpcHandlers.has(method)) {
|
|
26092
|
+
throw Error("RPC handler already registered for method ".concat(method, ", unregisterRpcMethod before trying to register again"));
|
|
26093
|
+
}
|
|
26094
|
+
this.rpcHandlers.set(method, handler);
|
|
26095
|
+
}
|
|
26096
|
+
unregisterRpcMethod(method) {
|
|
26097
|
+
this.rpcHandlers.delete(method);
|
|
26098
|
+
}
|
|
26099
|
+
/**
|
|
26100
|
+
* Handle an incoming RPCRequest message containing a payload.
|
|
26101
|
+
* This handles "version 1" of rpc requests.
|
|
26102
|
+
* @internal
|
|
26103
|
+
*/
|
|
26104
|
+
handleIncomingRpcRequest(callerIdentity, rpcRequest) {
|
|
26105
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26106
|
+
var _a;
|
|
26107
|
+
this.publishRpcAck(callerIdentity, rpcRequest.id);
|
|
26108
|
+
if (rpcRequest.version !== 1) {
|
|
26109
|
+
this.publishRpcResponsePacket(callerIdentity, rpcRequest.id, null, RpcError.builtIn('UNSUPPORTED_VERSION'));
|
|
26110
|
+
return;
|
|
26111
|
+
}
|
|
26112
|
+
const handler = this.rpcHandlers.get(rpcRequest.method);
|
|
26113
|
+
if (!handler) {
|
|
26114
|
+
this.publishRpcResponsePacket(callerIdentity, rpcRequest.id, null, RpcError.builtIn('UNSUPPORTED_METHOD'));
|
|
26115
|
+
return;
|
|
26116
|
+
}
|
|
26117
|
+
let response;
|
|
26118
|
+
try {
|
|
26119
|
+
response = yield handler({
|
|
26120
|
+
requestId: rpcRequest.id,
|
|
26121
|
+
callerIdentity,
|
|
26122
|
+
payload: rpcRequest.payload,
|
|
26123
|
+
responseTimeout: rpcRequest.responseTimeoutMs
|
|
26124
|
+
});
|
|
26125
|
+
} catch (error) {
|
|
26126
|
+
let responseError;
|
|
26127
|
+
if (error instanceof RpcError) {
|
|
26128
|
+
responseError = error;
|
|
26129
|
+
} else {
|
|
26130
|
+
this.log.warn("Uncaught error returned by RPC handler for ".concat(rpcRequest.method, ". Returning APPLICATION_ERROR instead."), error);
|
|
26131
|
+
responseError = RpcError.builtIn('APPLICATION_ERROR', "Uncaught error: ".concat((_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : error), {
|
|
26132
|
+
cause: error
|
|
26133
|
+
});
|
|
26134
|
+
}
|
|
26135
|
+
this.publishRpcResponsePacket(callerIdentity, rpcRequest.id, null, responseError);
|
|
26136
|
+
return;
|
|
26137
|
+
}
|
|
26138
|
+
yield this.publishRpcResponse(callerIdentity, rpcRequest.id, response !== null && response !== void 0 ? response : '');
|
|
26139
|
+
});
|
|
26140
|
+
}
|
|
26141
|
+
/**
|
|
26142
|
+
* Handle an incoming data stream containing a RPC request payload.
|
|
26143
|
+
* This handles "version 2" of rpc requests.
|
|
26144
|
+
* @internal
|
|
26145
|
+
*/
|
|
26146
|
+
handleIncomingDataStream(reader, callerIdentity, dataStreamAttrs) {
|
|
26147
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26148
|
+
const requestId = dataStreamAttrs[RpcRequestAttrs.RPC_REQUEST_ID];
|
|
26149
|
+
const method = dataStreamAttrs[RpcRequestAttrs.RPC_REQUEST_METHOD];
|
|
26150
|
+
const responseTimeout = parseInt(dataStreamAttrs[RpcRequestAttrs.RPC_REQUEST_RESPONSE_TIMEOUT_MS], 10);
|
|
26151
|
+
const version = parseInt(dataStreamAttrs[RpcRequestAttrs.RPC_REQUEST_VERSION], 10);
|
|
26152
|
+
if (!requestId || !method || Number.isNaN(responseTimeout) || Number.isNaN(version)) {
|
|
26153
|
+
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."));
|
|
26154
|
+
this.publishRpcResponsePacket(callerIdentity, requestId, null, RpcError.builtIn('APPLICATION_ERROR', 'RPC data stream malformed'));
|
|
26155
|
+
return;
|
|
26156
|
+
}
|
|
26157
|
+
this.publishRpcAck(callerIdentity, requestId);
|
|
26158
|
+
if (version !== RPC_VERSION_V2) {
|
|
26159
|
+
this.publishRpcResponsePacket(callerIdentity, requestId, null, RpcError.builtIn('UNSUPPORTED_VERSION'));
|
|
26160
|
+
return;
|
|
26161
|
+
}
|
|
26162
|
+
let payload;
|
|
26163
|
+
try {
|
|
26164
|
+
payload = yield reader.readAll();
|
|
26165
|
+
} catch (e) {
|
|
26166
|
+
this.log.warn("Error reading RPC request payload: ".concat(e));
|
|
26167
|
+
this.publishRpcResponsePacket(callerIdentity, requestId, null, RpcError.builtIn('APPLICATION_ERROR', 'Error reading RPC request payload', {
|
|
26168
|
+
cause: e
|
|
26169
|
+
}));
|
|
26170
|
+
return;
|
|
26171
|
+
}
|
|
26172
|
+
const handler = this.rpcHandlers.get(method);
|
|
26173
|
+
if (!handler) {
|
|
26174
|
+
this.publishRpcResponsePacket(callerIdentity, requestId, null, RpcError.builtIn('UNSUPPORTED_METHOD'));
|
|
26175
|
+
return;
|
|
26176
|
+
}
|
|
26177
|
+
let response;
|
|
26178
|
+
try {
|
|
26179
|
+
response = yield handler({
|
|
26180
|
+
requestId,
|
|
26181
|
+
callerIdentity,
|
|
26182
|
+
payload,
|
|
26183
|
+
responseTimeout
|
|
26184
|
+
});
|
|
26185
|
+
} catch (error) {
|
|
26186
|
+
let responseError;
|
|
26187
|
+
if (error instanceof RpcError) {
|
|
26188
|
+
responseError = error;
|
|
26189
|
+
} else {
|
|
26190
|
+
this.log.warn("Uncaught error returned by RPC handler for ".concat(method, ". Returning APPLICATION_ERROR instead."), error);
|
|
26191
|
+
responseError = RpcError.builtIn('APPLICATION_ERROR');
|
|
26192
|
+
}
|
|
26193
|
+
this.publishRpcResponsePacket(callerIdentity, requestId, null, responseError);
|
|
26194
|
+
return;
|
|
26195
|
+
}
|
|
26196
|
+
yield this.publishRpcResponse(callerIdentity, requestId, response !== null && response !== void 0 ? response : '');
|
|
26197
|
+
});
|
|
26198
|
+
}
|
|
26199
|
+
publishRpcAck(destinationIdentity, requestId) {
|
|
26200
|
+
this.emit('sendDataPacket', {
|
|
26201
|
+
packet: new DataPacket({
|
|
26202
|
+
destinationIdentities: [destinationIdentity],
|
|
26203
|
+
kind: DataPacket_Kind.RELIABLE,
|
|
26204
|
+
value: {
|
|
26205
|
+
case: 'rpcAck',
|
|
26206
|
+
value: new RpcAck({
|
|
26207
|
+
requestId
|
|
26208
|
+
})
|
|
26209
|
+
}
|
|
26210
|
+
})
|
|
26211
|
+
});
|
|
26212
|
+
}
|
|
26213
|
+
publishRpcResponsePacket(destinationIdentity, requestId, payload, error) {
|
|
26214
|
+
this.emit('sendDataPacket', {
|
|
26215
|
+
packet: new DataPacket({
|
|
26216
|
+
destinationIdentities: [destinationIdentity],
|
|
26217
|
+
kind: DataPacket_Kind.RELIABLE,
|
|
26218
|
+
value: {
|
|
26219
|
+
case: 'rpcResponse',
|
|
26220
|
+
value: new RpcResponse({
|
|
26221
|
+
requestId,
|
|
26222
|
+
value: error ? {
|
|
26223
|
+
case: 'error',
|
|
26224
|
+
value: error.toProto()
|
|
26225
|
+
} : {
|
|
26226
|
+
case: 'payload',
|
|
26227
|
+
value: payload !== null && payload !== void 0 ? payload : ''
|
|
26228
|
+
}
|
|
26229
|
+
})
|
|
26230
|
+
}
|
|
26231
|
+
})
|
|
26232
|
+
});
|
|
26233
|
+
}
|
|
26234
|
+
/**
|
|
26235
|
+
* Send a successful RPC response payload, choosing the transport based on
|
|
26236
|
+
* the caller's client protocol version.
|
|
26237
|
+
*/
|
|
26238
|
+
publishRpcResponse(destinationIdentity, requestId, payload) {
|
|
26239
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26240
|
+
const callerClientProtocol = this.getRemoteParticipantClientProtocol(destinationIdentity);
|
|
26241
|
+
if (callerClientProtocol >= CLIENT_PROTOCOL_DATA_STREAM_RPC) {
|
|
26242
|
+
// Send response as a data stream
|
|
26243
|
+
const writer = yield this.outgoingDataStreamManager.streamText({
|
|
26244
|
+
topic: RPC_RESPONSE_DATA_STREAM_TOPIC,
|
|
26245
|
+
destinationIdentities: [destinationIdentity],
|
|
26246
|
+
attributes: {
|
|
26247
|
+
[RpcRequestAttrs.RPC_REQUEST_ID]: requestId
|
|
26248
|
+
}
|
|
26249
|
+
});
|
|
26250
|
+
yield writer.write(payload);
|
|
26251
|
+
yield writer.close();
|
|
26252
|
+
return;
|
|
26253
|
+
}
|
|
26254
|
+
// Legacy client: enforce size limit and send uncompressed payload inline
|
|
26255
|
+
const responseBytes = byteLength(payload);
|
|
26256
|
+
if (responseBytes > MAX_V1_PAYLOAD_BYTES) {
|
|
26257
|
+
this.log.warn("RPC Response payload too large for request ".concat(requestId, ". To send larger responses, consider updating the sending client."));
|
|
26258
|
+
this.publishRpcResponsePacket(destinationIdentity, requestId, null, RpcError.builtIn('RESPONSE_PAYLOAD_TOO_LARGE'));
|
|
26259
|
+
return;
|
|
26260
|
+
}
|
|
26261
|
+
this.publishRpcResponsePacket(destinationIdentity, requestId, payload, null);
|
|
26262
|
+
});
|
|
26263
|
+
}
|
|
26264
|
+
}class RemoteAudioTrack extends RemoteTrack {
|
|
26265
|
+
constructor(mediaTrack, sid, receiver, audioContext, audioOutput, loggerOptions) {
|
|
26266
|
+
super(mediaTrack, sid, Track.Kind.Audio, receiver, loggerOptions);
|
|
26267
|
+
this.monitorReceiver = () => __awaiter(this, void 0, void 0, function* () {
|
|
26268
|
+
if (!this.receiver) {
|
|
26269
|
+
this._currentBitrate = 0;
|
|
26270
|
+
return;
|
|
26271
|
+
}
|
|
26272
|
+
const stats = yield this.getReceiverStats();
|
|
26273
|
+
if (stats && this.prevStats && this.receiver) {
|
|
26274
|
+
this._currentBitrate = computeBitrate(stats, this.prevStats);
|
|
26275
|
+
}
|
|
26276
|
+
this.prevStats = stats;
|
|
26277
|
+
});
|
|
26278
|
+
this.audioContext = audioContext;
|
|
26279
|
+
this.webAudioPluginNodes = [];
|
|
26280
|
+
if (audioOutput) {
|
|
26281
|
+
this.sinkId = audioOutput.deviceId;
|
|
26282
|
+
}
|
|
26283
|
+
}
|
|
26284
|
+
/**
|
|
26285
|
+
* sets the volume for all attached audio elements
|
|
26286
|
+
*/
|
|
26287
|
+
setVolume(volume) {
|
|
26288
|
+
var _a;
|
|
26289
|
+
for (const el of this.attachedElements) {
|
|
26290
|
+
if (this.audioContext) {
|
|
26291
|
+
(_a = this.gainNode) === null || _a === void 0 ? void 0 : _a.gain.setTargetAtTime(volume, 0, 0.1);
|
|
26292
|
+
} else {
|
|
26293
|
+
el.volume = volume;
|
|
26294
|
+
}
|
|
26295
|
+
}
|
|
26296
|
+
if (isReactNative()) {
|
|
26297
|
+
// @ts-ignore
|
|
26298
|
+
this._mediaStreamTrack._setVolume(volume);
|
|
26299
|
+
}
|
|
26300
|
+
this.elementVolume = volume;
|
|
26301
|
+
}
|
|
26302
|
+
/**
|
|
26303
|
+
* gets the volume of attached audio elements (loudest)
|
|
26304
|
+
*/
|
|
26305
|
+
getVolume() {
|
|
26306
|
+
if (this.elementVolume) {
|
|
26307
|
+
return this.elementVolume;
|
|
26308
|
+
}
|
|
26309
|
+
if (isReactNative()) {
|
|
26310
|
+
// RN volume value defaults to 1.0 if hasn't been changed.
|
|
26311
|
+
return 1.0;
|
|
26312
|
+
}
|
|
26313
|
+
let highestVolume = 0;
|
|
26314
|
+
this.attachedElements.forEach(element => {
|
|
26315
|
+
if (element.volume > highestVolume) {
|
|
26316
|
+
highestVolume = element.volume;
|
|
26317
|
+
}
|
|
26318
|
+
});
|
|
26319
|
+
return highestVolume;
|
|
26320
|
+
}
|
|
26321
|
+
/**
|
|
26322
|
+
* calls setSinkId on all attached elements, if supported
|
|
26323
|
+
* @param deviceId audio output device
|
|
26324
|
+
*/
|
|
26325
|
+
setSinkId(deviceId) {
|
|
26326
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26327
|
+
this.sinkId = deviceId;
|
|
26328
|
+
yield Promise.all(this.attachedElements.map(elm => {
|
|
26329
|
+
if (!supportsSetSinkId(elm)) {
|
|
26330
|
+
return;
|
|
26331
|
+
}
|
|
26332
|
+
/* @ts-ignore */
|
|
26333
|
+
return elm.setSinkId(deviceId);
|
|
26334
|
+
}));
|
|
26335
|
+
});
|
|
26336
|
+
}
|
|
26337
|
+
attach(element) {
|
|
26338
|
+
const needsNewWebAudioConnection = this.attachedElements.length === 0;
|
|
26339
|
+
if (!element) {
|
|
26340
|
+
element = super.attach();
|
|
26341
|
+
} else {
|
|
26342
|
+
super.attach(element);
|
|
26343
|
+
}
|
|
26344
|
+
if (this.sinkId && supportsSetSinkId(element)) {
|
|
26345
|
+
element.setSinkId(this.sinkId).catch(e => {
|
|
26346
|
+
this.log.error('Failed to set sink id on remote audio track', e, this.logContext);
|
|
26347
|
+
});
|
|
26348
|
+
}
|
|
26349
|
+
if (this.audioContext && needsNewWebAudioConnection) {
|
|
26350
|
+
this.log.debug('using audio context mapping', this.logContext);
|
|
26351
|
+
this.connectWebAudio(this.audioContext, element);
|
|
26352
|
+
element.volume = 0;
|
|
26353
|
+
element.muted = true;
|
|
26354
|
+
}
|
|
26355
|
+
if (this.elementVolume) {
|
|
26356
|
+
// make sure volume setting is being applied to the newly attached element
|
|
26357
|
+
this.setVolume(this.elementVolume);
|
|
26358
|
+
}
|
|
26359
|
+
return element;
|
|
26360
|
+
}
|
|
26361
|
+
detach(element) {
|
|
26362
|
+
let detached;
|
|
26363
|
+
if (!element) {
|
|
26364
|
+
detached = super.detach();
|
|
26365
|
+
this.disconnectWebAudio();
|
|
26366
|
+
} else {
|
|
26367
|
+
detached = super.detach(element);
|
|
26368
|
+
// if there are still any attached elements after detaching, connect webaudio to the first element that's left
|
|
26369
|
+
// disconnect webaudio otherwise
|
|
26370
|
+
if (this.audioContext) {
|
|
25973
26371
|
if (this.attachedElements.length > 0) {
|
|
25974
26372
|
this.connectWebAudio(this.audioContext, this.attachedElements[0]);
|
|
25975
26373
|
} else {
|
|
@@ -26726,7 +27124,7 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
26726
27124
|
});
|
|
26727
27125
|
}class LocalParticipant extends Participant {
|
|
26728
27126
|
/** @internal */
|
|
26729
|
-
constructor(sid, identity, engine, options,
|
|
27127
|
+
constructor(sid, identity, engine, options, roomOutgoingDataStreamManager, roomOutgoingDataTrackManager, rpcClientManager, rpcServerManager) {
|
|
26730
27128
|
super(sid, identity, undefined, undefined, undefined, {
|
|
26731
27129
|
loggerName: options.loggerName,
|
|
26732
27130
|
loggerContextCb: () => this.engine.logContext
|
|
@@ -26738,8 +27136,6 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
26738
27136
|
this.encryptionType = Encryption_Type.NONE;
|
|
26739
27137
|
this.e2eeStateMutex = new _();
|
|
26740
27138
|
this.enabledPublishVideoCodecs = [];
|
|
26741
|
-
this.pendingAcks = new Map();
|
|
26742
|
-
this.pendingResponses = new Map();
|
|
26743
27139
|
this.handleReconnecting = () => {
|
|
26744
27140
|
if (!this.reconnectFuture) {
|
|
26745
27141
|
this.reconnectFuture = new Future();
|
|
@@ -26820,25 +27216,6 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
26820
27216
|
}
|
|
26821
27217
|
}
|
|
26822
27218
|
};
|
|
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
27219
|
this.updateTrackSubscriptionPermissions = () => {
|
|
26843
27220
|
this.log.debug('updating track subscription permissions', {
|
|
26844
27221
|
allParticipantsAllowed: this.allParticipantsAllowedToSubscribe,
|
|
@@ -26988,9 +27365,10 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
26988
27365
|
this.setupEngine(engine);
|
|
26989
27366
|
this.activeDeviceMap = new Map([['audioinput', 'default'], ['videoinput', 'default'], ['audiooutput', 'default']]);
|
|
26990
27367
|
this.pendingSignalRequests = new Map();
|
|
26991
|
-
this.rpcHandlers = roomRpcHandlers;
|
|
26992
27368
|
this.roomOutgoingDataStreamManager = roomOutgoingDataStreamManager;
|
|
26993
27369
|
this.roomOutgoingDataTrackManager = roomOutgoingDataTrackManager;
|
|
27370
|
+
this.rpcClientManager = rpcClientManager;
|
|
27371
|
+
this.rpcServerManager = rpcServerManager;
|
|
26994
27372
|
}
|
|
26995
27373
|
get lastCameraError() {
|
|
26996
27374
|
return this.cameraError;
|
|
@@ -27033,7 +27411,7 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
27033
27411
|
if ((_a = this.signalConnectedFuture) === null || _a === void 0 ? void 0 : _a.isResolved) {
|
|
27034
27412
|
this.signalConnectedFuture = undefined;
|
|
27035
27413
|
}
|
|
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)
|
|
27414
|
+
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
27415
|
}
|
|
27038
27416
|
/**
|
|
27039
27417
|
* Sets and updates the metadata of the local participant.
|
|
@@ -28336,76 +28714,23 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
28336
28714
|
* @returns A promise that resolves with the response payload or rejects with an error.
|
|
28337
28715
|
* @throws Error on failure. Details in `message`.
|
|
28338
28716
|
*/
|
|
28339
|
-
performRpc(
|
|
28340
|
-
|
|
28341
|
-
|
|
28342
|
-
|
|
28343
|
-
|
|
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
|
-
}));
|
|
28717
|
+
performRpc(params) {
|
|
28718
|
+
return this.rpcClientManager.performRpc(params).then(_ref3 => {
|
|
28719
|
+
let [_id, completionPromise] = _ref3;
|
|
28720
|
+
return completionPromise;
|
|
28721
|
+
});
|
|
28394
28722
|
}
|
|
28395
28723
|
/**
|
|
28396
28724
|
* @deprecated use `room.registerRpcMethod` instead
|
|
28397
28725
|
*/
|
|
28398
28726
|
registerRpcMethod(method, handler) {
|
|
28399
|
-
|
|
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);
|
|
28727
|
+
this.rpcServerManager.registerRpcMethod(method, handler);
|
|
28403
28728
|
}
|
|
28404
28729
|
/**
|
|
28405
28730
|
* @deprecated use `room.unregisterRpcMethod` instead
|
|
28406
28731
|
*/
|
|
28407
28732
|
unregisterRpcMethod(method) {
|
|
28408
|
-
this.
|
|
28733
|
+
this.rpcServerManager.unregisterRpcMethod(method);
|
|
28409
28734
|
}
|
|
28410
28735
|
/**
|
|
28411
28736
|
* Control who can subscribe to LocalParticipant's published tracks.
|
|
@@ -28432,63 +28757,6 @@ class Participant extends eventsExports.EventEmitter {
|
|
|
28432
28757
|
this.updateTrackSubscriptionPermissions();
|
|
28433
28758
|
}
|
|
28434
28759
|
}
|
|
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
28760
|
/** @internal */
|
|
28493
28761
|
setEnabledPublishCodecs(codecs) {
|
|
28494
28762
|
this.enabledPublishVideoCodecs = codecs.filter(c => c.mime.split('/')[0].toLowerCase() === 'video');
|
|
@@ -28955,7 +29223,7 @@ class DeferrableMap extends Map {
|
|
|
28955
29223
|
return new RemoteDataTrack(info, manager, {
|
|
28956
29224
|
publisherIdentity: pi.identity
|
|
28957
29225
|
});
|
|
28958
|
-
}));
|
|
29226
|
+
}), pi.clientProtocol);
|
|
28959
29227
|
}
|
|
28960
29228
|
get logContext() {
|
|
28961
29229
|
return Object.assign(Object.assign({}, super.logContext), {
|
|
@@ -28967,6 +29235,7 @@ class DeferrableMap extends Map {
|
|
|
28967
29235
|
constructor(signalClient, sid, identity, name, metadata, attributes, loggerOptions) {
|
|
28968
29236
|
let kind = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : ParticipantInfo_Kind.STANDARD;
|
|
28969
29237
|
let remoteDataTracks = arguments.length > 8 && arguments[8] !== undefined ? arguments[8] : [];
|
|
29238
|
+
let clientProtocol = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : CLIENT_PROTOCOL_DEFAULT;
|
|
28970
29239
|
super(sid, identity || '', name, metadata, attributes, loggerOptions, kind);
|
|
28971
29240
|
this.signalClient = signalClient;
|
|
28972
29241
|
this.trackPublications = new Map();
|
|
@@ -28976,6 +29245,7 @@ class DeferrableMap extends Map {
|
|
|
28976
29245
|
return [remoteDataTrack.info.name, remoteDataTrack];
|
|
28977
29246
|
}));
|
|
28978
29247
|
this.volumeMap = new Map();
|
|
29248
|
+
this.clientProtocol = clientProtocol;
|
|
28979
29249
|
}
|
|
28980
29250
|
addTrackPublication(publication) {
|
|
28981
29251
|
super.addTrackPublication(publication);
|
|
@@ -29277,7 +29547,6 @@ class Room extends eventsExports.EventEmitter {
|
|
|
29277
29547
|
this.log = livekitLogger;
|
|
29278
29548
|
this.bufferedEvents = [];
|
|
29279
29549
|
this.isResuming = false;
|
|
29280
|
-
this.rpcHandlers = new Map();
|
|
29281
29550
|
this.connect = (url, token, opts) => __awaiter(this, void 0, void 0, function* () {
|
|
29282
29551
|
var _a;
|
|
29283
29552
|
if (!isBrowserSupported()) {
|
|
@@ -29834,7 +30103,22 @@ class Room extends eventsExports.EventEmitter {
|
|
|
29834
30103
|
this.handleDataStream(packet, encryptionType);
|
|
29835
30104
|
} else if (packet.value.case === 'rpcRequest') {
|
|
29836
30105
|
const rpc = packet.value.value;
|
|
29837
|
-
this.handleIncomingRpcRequest(packet.participantIdentity, rpc
|
|
30106
|
+
this.rpcServerManager.handleIncomingRpcRequest(packet.participantIdentity, rpc);
|
|
30107
|
+
} else if (packet.value.case === 'rpcResponse') {
|
|
30108
|
+
const rpcResponse = packet.value.value;
|
|
30109
|
+
switch (rpcResponse.value.case) {
|
|
30110
|
+
case 'payload':
|
|
30111
|
+
this.rpcClientManager.handleIncomingRpcResponseSuccess(rpcResponse.requestId, rpcResponse.value.value);
|
|
30112
|
+
break;
|
|
30113
|
+
case 'error':
|
|
30114
|
+
this.rpcClientManager.handleIncomingRpcResponseFailure(rpcResponse.requestId, RpcError.fromProto(rpcResponse.value.value));
|
|
30115
|
+
break;
|
|
30116
|
+
default:
|
|
30117
|
+
this.log.warn("Unknown rpcResponse.value.case: ".concat(rpcResponse.value.case), this.logContext);
|
|
30118
|
+
break;
|
|
30119
|
+
}
|
|
30120
|
+
} else if (packet.value.case === 'rpcAck') {
|
|
30121
|
+
this.rpcClientManager.handleIncomingRpcAck(packet.value.value.requestId);
|
|
29838
30122
|
}
|
|
29839
30123
|
};
|
|
29840
30124
|
this.handleUserPacket = (participant, userPacket, kind, encryptionType) => {
|
|
@@ -29926,6 +30210,10 @@ class Room extends eventsExports.EventEmitter {
|
|
|
29926
30210
|
}
|
|
29927
30211
|
});
|
|
29928
30212
|
};
|
|
30213
|
+
this.getRemoteParticipantClientProtocol = identity => {
|
|
30214
|
+
var _a, _b;
|
|
30215
|
+
return (_b = (_a = this.remoteParticipants.get(identity)) === null || _a === void 0 ? void 0 : _a.clientProtocol) !== null && _b !== void 0 ? _b : CLIENT_PROTOCOL_DEFAULT;
|
|
30216
|
+
};
|
|
29929
30217
|
this.onLocalParticipantMetadataChanged = metadata => {
|
|
29930
30218
|
this.emit(RoomEvent.ParticipantMetadataChanged, metadata, this.localParticipant);
|
|
29931
30219
|
};
|
|
@@ -30043,8 +30331,28 @@ class Room extends eventsExports.EventEmitter {
|
|
|
30043
30331
|
} = _ref;
|
|
30044
30332
|
this.engine.sendLossyBytes(bytes, DataChannelKind.DATA_TRACK_LOSSY, 'wait').finally(() => this.outgoingDataTrackManager.handlePacketSendComplete(handle));
|
|
30045
30333
|
});
|
|
30334
|
+
this.registerRpcDataStreamHandler();
|
|
30335
|
+
this.rpcClientManager = new RpcClientManager(this.log, this.outgoingDataStreamManager, this.getRemoteParticipantClientProtocol, () => {
|
|
30336
|
+
var _a, _b;
|
|
30337
|
+
return (_b = (_a = this.engine.latestJoinResponse) === null || _a === void 0 ? void 0 : _a.serverInfo) === null || _b === void 0 ? void 0 : _b.version;
|
|
30338
|
+
});
|
|
30339
|
+
this.rpcClientManager.on('sendDataPacket', _ref2 => {
|
|
30340
|
+
let {
|
|
30341
|
+
packet
|
|
30342
|
+
} = _ref2;
|
|
30343
|
+
var _a;
|
|
30344
|
+
(_a = this.engine) === null || _a === void 0 ? void 0 : _a.sendDataPacket(packet, DataChannelKind.RELIABLE);
|
|
30345
|
+
});
|
|
30346
|
+
this.rpcServerManager = new RpcServerManager(this.log, this.outgoingDataStreamManager, this.getRemoteParticipantClientProtocol);
|
|
30347
|
+
this.rpcServerManager.on('sendDataPacket', _ref3 => {
|
|
30348
|
+
let {
|
|
30349
|
+
packet
|
|
30350
|
+
} = _ref3;
|
|
30351
|
+
var _a;
|
|
30352
|
+
(_a = this.engine) === null || _a === void 0 ? void 0 : _a.sendDataPacket(packet, DataChannelKind.RELIABLE);
|
|
30353
|
+
});
|
|
30046
30354
|
this.disconnectLock = new _();
|
|
30047
|
-
this.localParticipant = new LocalParticipant('', '', this.engine, this.options, this.
|
|
30355
|
+
this.localParticipant = new LocalParticipant('', '', this.engine, this.options, this.outgoingDataStreamManager, this.outgoingDataTrackManager, this.rpcClientManager, this.rpcServerManager);
|
|
30048
30356
|
this.setupPacketTrailer();
|
|
30049
30357
|
if (this.options.e2ee || this.options.encryption) {
|
|
30050
30358
|
this.setupE2EE();
|
|
@@ -30113,10 +30421,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
30113
30421
|
* Other errors thrown in your handler will not be transmitted as-is, and will instead arrive to the caller as `1500` ("Application Error").
|
|
30114
30422
|
*/
|
|
30115
30423
|
registerRpcMethod(method, handler) {
|
|
30116
|
-
|
|
30117
|
-
throw Error("RPC handler already registered for method ".concat(method, ", unregisterRpcMethod before trying to register again"));
|
|
30118
|
-
}
|
|
30119
|
-
this.rpcHandlers.set(method, handler);
|
|
30424
|
+
this.rpcServerManager.registerRpcMethod(method, handler);
|
|
30120
30425
|
}
|
|
30121
30426
|
/**
|
|
30122
30427
|
* Unregisters a previously registered RPC method.
|
|
@@ -30124,7 +30429,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
30124
30429
|
* @param method - The name of the RPC method to unregister
|
|
30125
30430
|
*/
|
|
30126
30431
|
unregisterRpcMethod(method) {
|
|
30127
|
-
this.
|
|
30432
|
+
this.rpcServerManager.unregisterRpcMethod(method);
|
|
30128
30433
|
}
|
|
30129
30434
|
/**
|
|
30130
30435
|
* @experimental
|
|
@@ -30313,8 +30618,8 @@ class Room extends eventsExports.EventEmitter {
|
|
|
30313
30618
|
}
|
|
30314
30619
|
this.outgoingDataTrackManager.receivedSfuUnpublishResponse(event.info.pubHandle);
|
|
30315
30620
|
}).on(EngineEvent.DataTrackSubscriberHandles, event => {
|
|
30316
|
-
const handleToSidMapping = new Map(Object.entries(event.subHandles).map(
|
|
30317
|
-
let [key, value] =
|
|
30621
|
+
const handleToSidMapping = new Map(Object.entries(event.subHandles).map(_ref4 => {
|
|
30622
|
+
let [key, value] = _ref4;
|
|
30318
30623
|
return [parseInt(key, 10), value.trackSid];
|
|
30319
30624
|
}));
|
|
30320
30625
|
this.incomingDataTrackManager.receivedSfuSubscriberHandles(handleToSidMapping);
|
|
@@ -30768,10 +31073,10 @@ class Room extends eventsExports.EventEmitter {
|
|
|
30768
31073
|
}
|
|
30769
31074
|
}
|
|
30770
31075
|
handleLocalTrackSubscribed(subscribedSid) {
|
|
30771
|
-
const findPublication = () => this.localParticipant.getTrackPublications().find(
|
|
31076
|
+
const findPublication = () => this.localParticipant.getTrackPublications().find(_ref5 => {
|
|
30772
31077
|
let {
|
|
30773
31078
|
trackSid
|
|
30774
|
-
} =
|
|
31079
|
+
} = _ref5;
|
|
30775
31080
|
return trackSid === subscribedSid;
|
|
30776
31081
|
});
|
|
30777
31082
|
const trackPublication = findPublication();
|
|
@@ -30877,7 +31182,6 @@ class Room extends eventsExports.EventEmitter {
|
|
|
30877
31182
|
}
|
|
30878
31183
|
}
|
|
30879
31184
|
handleParticipantDisconnected(identity, participant) {
|
|
30880
|
-
var _a;
|
|
30881
31185
|
// remove and send event
|
|
30882
31186
|
this.remoteParticipants.delete(identity);
|
|
30883
31187
|
if (!participant) {
|
|
@@ -30890,45 +31194,7 @@ class Room extends eventsExports.EventEmitter {
|
|
|
30890
31194
|
});
|
|
30891
31195
|
this.emit(RoomEvent.ParticipantDisconnected, participant);
|
|
30892
31196
|
participant.setDisconnected();
|
|
30893
|
-
|
|
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
|
-
});
|
|
31197
|
+
this.rpcClientManager.handleParticipantDisconnected(participant.identity);
|
|
30932
31198
|
}
|
|
30933
31199
|
/**
|
|
30934
31200
|
* attempt to select the default devices if the previously selected devices are no longer available after a device change event
|
|
@@ -31134,6 +31400,30 @@ class Room extends eventsExports.EventEmitter {
|
|
|
31134
31400
|
return this.remoteParticipants.get(identity);
|
|
31135
31401
|
}
|
|
31136
31402
|
}
|
|
31403
|
+
registerRpcDataStreamHandler() {
|
|
31404
|
+
this.incomingDataStreamManager.registerTextStreamHandler(RPC_REQUEST_DATA_STREAM_TOPIC, (reader_1, _a) => __awaiter(this, [reader_1, _a], void 0, function (reader, _ref6) {
|
|
31405
|
+
var _this4 = this;
|
|
31406
|
+
let {
|
|
31407
|
+
identity
|
|
31408
|
+
} = _ref6;
|
|
31409
|
+
return function* () {
|
|
31410
|
+
var _b;
|
|
31411
|
+
const attributes = (_b = reader.info.attributes) !== null && _b !== void 0 ? _b : {};
|
|
31412
|
+
yield _this4.rpcServerManager.handleIncomingDataStream(reader, identity, attributes);
|
|
31413
|
+
}();
|
|
31414
|
+
}));
|
|
31415
|
+
this.incomingDataStreamManager.registerTextStreamHandler(RPC_RESPONSE_DATA_STREAM_TOPIC, (reader_1, _a) => __awaiter(this, [reader_1, _a], void 0, function (reader, _ref7) {
|
|
31416
|
+
var _this5 = this;
|
|
31417
|
+
let {
|
|
31418
|
+
identity
|
|
31419
|
+
} = _ref7;
|
|
31420
|
+
return function* () {
|
|
31421
|
+
var _b;
|
|
31422
|
+
const attributes = (_b = reader.info.attributes) !== null && _b !== void 0 ? _b : {};
|
|
31423
|
+
yield _this5.rpcClientManager.handleIncomingDataStream(reader, identity, attributes);
|
|
31424
|
+
}();
|
|
31425
|
+
}));
|
|
31426
|
+
}
|
|
31137
31427
|
registerConnectionReconcile() {
|
|
31138
31428
|
this.clearConnectionReconcile();
|
|
31139
31429
|
let consecutiveFailures = 0;
|
|
@@ -31179,8 +31469,8 @@ class Room extends eventsExports.EventEmitter {
|
|
|
31179
31469
|
return true;
|
|
31180
31470
|
}
|
|
31181
31471
|
emitBufferedEvents() {
|
|
31182
|
-
this.bufferedEvents.forEach(
|
|
31183
|
-
let [ev, args] =
|
|
31472
|
+
this.bufferedEvents.forEach(_ref8 => {
|
|
31473
|
+
let [ev, args] = _ref8;
|
|
31184
31474
|
this.emit(ev, ...args);
|
|
31185
31475
|
});
|
|
31186
31476
|
this.bufferedEvents = [];
|
|
@@ -32766,4 +33056,4 @@ const serializers = {
|
|
|
32766
33056
|
json,
|
|
32767
33057
|
raw,
|
|
32768
33058
|
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
|
|
33059
|
+
};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
|