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
|
@@ -13,9 +13,6 @@ import {
|
|
|
13
13
|
ParticipantInfo,
|
|
14
14
|
RequestResponse,
|
|
15
15
|
RequestResponse_Reason,
|
|
16
|
-
RpcAck,
|
|
17
|
-
RpcRequest,
|
|
18
|
-
RpcResponse,
|
|
19
16
|
SimulcastCodec,
|
|
20
17
|
SipDTMF,
|
|
21
18
|
SubscribedQualityUpdate,
|
|
@@ -54,11 +51,11 @@ import {
|
|
|
54
51
|
} from '../errors';
|
|
55
52
|
import { EngineEvent, ParticipantEvent, TrackEvent } from '../events';
|
|
56
53
|
import {
|
|
57
|
-
MAX_PAYLOAD_BYTES,
|
|
58
54
|
type PerformRpcParams,
|
|
55
|
+
RpcClientManager,
|
|
59
56
|
RpcError,
|
|
60
57
|
type RpcInvocationData,
|
|
61
|
-
|
|
58
|
+
RpcServerManager,
|
|
62
59
|
} from '../rpc';
|
|
63
60
|
import LocalAudioTrack from '../track/LocalAudioTrack';
|
|
64
61
|
import LocalTrack from '../track/LocalTrack';
|
|
@@ -94,7 +91,6 @@ import {
|
|
|
94
91
|
} from '../types';
|
|
95
92
|
import {
|
|
96
93
|
Future,
|
|
97
|
-
compareVersions,
|
|
98
94
|
isAudioTrack,
|
|
99
95
|
isE2EESimulcastSupported,
|
|
100
96
|
isFireFox,
|
|
@@ -162,12 +158,14 @@ export default class LocalParticipant extends Participant {
|
|
|
162
158
|
|
|
163
159
|
private firstActiveAgent?: RemoteParticipant;
|
|
164
160
|
|
|
165
|
-
private rpcHandlers: Map<string, (data: RpcInvocationData) => Promise<string>>;
|
|
166
|
-
|
|
167
161
|
private roomOutgoingDataStreamManager: OutgoingDataStreamManager;
|
|
168
162
|
|
|
169
163
|
private roomOutgoingDataTrackManager: OutgoingDataTrackManager;
|
|
170
164
|
|
|
165
|
+
private rpcClientManager: RpcClientManager;
|
|
166
|
+
|
|
167
|
+
private rpcServerManager: RpcServerManager;
|
|
168
|
+
|
|
171
169
|
private pendingSignalRequests: Map<
|
|
172
170
|
number,
|
|
173
171
|
{
|
|
@@ -179,25 +177,16 @@ export default class LocalParticipant extends Participant {
|
|
|
179
177
|
|
|
180
178
|
private enabledPublishVideoCodecs: Codec[] = [];
|
|
181
179
|
|
|
182
|
-
private pendingAcks = new Map<string, { resolve: () => void; participantIdentity: string }>();
|
|
183
|
-
|
|
184
|
-
private pendingResponses = new Map<
|
|
185
|
-
string,
|
|
186
|
-
{
|
|
187
|
-
resolve: (payload: string | null, error: RpcError | null) => void;
|
|
188
|
-
participantIdentity: string;
|
|
189
|
-
}
|
|
190
|
-
>();
|
|
191
|
-
|
|
192
180
|
/** @internal */
|
|
193
181
|
constructor(
|
|
194
182
|
sid: string,
|
|
195
183
|
identity: string,
|
|
196
184
|
engine: RTCEngine,
|
|
197
185
|
options: InternalRoomOptions,
|
|
198
|
-
roomRpcHandlers: Map<string, (data: RpcInvocationData) => Promise<string>>,
|
|
199
186
|
roomOutgoingDataStreamManager: OutgoingDataStreamManager,
|
|
200
187
|
roomOutgoingDataTrackManager: OutgoingDataTrackManager,
|
|
188
|
+
rpcClientManager: RpcClientManager,
|
|
189
|
+
rpcServerManager: RpcServerManager,
|
|
201
190
|
) {
|
|
202
191
|
super(sid, identity, undefined, undefined, undefined, {
|
|
203
192
|
loggerName: options.loggerName,
|
|
@@ -215,9 +204,10 @@ export default class LocalParticipant extends Participant {
|
|
|
215
204
|
['audiooutput', 'default'],
|
|
216
205
|
]);
|
|
217
206
|
this.pendingSignalRequests = new Map();
|
|
218
|
-
this.rpcHandlers = roomRpcHandlers;
|
|
219
207
|
this.roomOutgoingDataStreamManager = roomOutgoingDataStreamManager;
|
|
220
208
|
this.roomOutgoingDataTrackManager = roomOutgoingDataTrackManager;
|
|
209
|
+
this.rpcClientManager = rpcClientManager;
|
|
210
|
+
this.rpcServerManager = rpcServerManager;
|
|
221
211
|
}
|
|
222
212
|
|
|
223
213
|
get lastCameraError(): Error | undefined {
|
|
@@ -277,8 +267,7 @@ export default class LocalParticipant extends Participant {
|
|
|
277
267
|
.on(EngineEvent.LocalTrackUnpublished, this.handleLocalTrackUnpublished)
|
|
278
268
|
.on(EngineEvent.SubscribedQualityUpdate, this.handleSubscribedQualityUpdate)
|
|
279
269
|
.on(EngineEvent.Closing, this.handleClosing)
|
|
280
|
-
.on(EngineEvent.SignalRequestResponse, this.handleSignalRequestResponse)
|
|
281
|
-
.on(EngineEvent.DataPacketReceived, this.handleDataPacket);
|
|
270
|
+
.on(EngineEvent.SignalRequestResponse, this.handleSignalRequestResponse);
|
|
282
271
|
}
|
|
283
272
|
|
|
284
273
|
private handleReconnecting = () => {
|
|
@@ -362,27 +351,6 @@ export default class LocalParticipant extends Participant {
|
|
|
362
351
|
}
|
|
363
352
|
};
|
|
364
353
|
|
|
365
|
-
private handleDataPacket = (packet: DataPacket) => {
|
|
366
|
-
switch (packet.value.case) {
|
|
367
|
-
case 'rpcResponse':
|
|
368
|
-
let rpcResponse = packet.value.value as RpcResponse;
|
|
369
|
-
let payload: string | null = null;
|
|
370
|
-
let error: RpcError | null = null;
|
|
371
|
-
|
|
372
|
-
if (rpcResponse.value.case === 'payload') {
|
|
373
|
-
payload = rpcResponse.value.value;
|
|
374
|
-
} else if (rpcResponse.value.case === 'error') {
|
|
375
|
-
error = RpcError.fromProto(rpcResponse.value.value);
|
|
376
|
-
}
|
|
377
|
-
this.handleIncomingRpcResponse(rpcResponse.requestId, payload, error);
|
|
378
|
-
break;
|
|
379
|
-
case 'rpcAck':
|
|
380
|
-
let rpcAck = packet.value.value as RpcAck;
|
|
381
|
-
this.handleIncomingRpcAck(rpcAck.requestId);
|
|
382
|
-
break;
|
|
383
|
-
}
|
|
384
|
-
};
|
|
385
|
-
|
|
386
354
|
/**
|
|
387
355
|
* Sets and updates the metadata of the local participant.
|
|
388
356
|
* Note: this requires `canUpdateOwnMetadata` permission.
|
|
@@ -1883,69 +1851,9 @@ export default class LocalParticipant extends Participant {
|
|
|
1883
1851
|
* @returns A promise that resolves with the response payload or rejects with an error.
|
|
1884
1852
|
* @throws Error on failure. Details in `message`.
|
|
1885
1853
|
*/
|
|
1886
|
-
performRpc({
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
payload,
|
|
1890
|
-
responseTimeout = 15000,
|
|
1891
|
-
}: PerformRpcParams): TypedPromise<string, RpcError> {
|
|
1892
|
-
const maxRoundTripLatency = 7000;
|
|
1893
|
-
const minEffectiveTimeout = maxRoundTripLatency + 1000;
|
|
1894
|
-
|
|
1895
|
-
return new TypedPromise<string, RpcError>(async (resolve, reject) => {
|
|
1896
|
-
if (byteLength(payload) > MAX_PAYLOAD_BYTES) {
|
|
1897
|
-
reject(RpcError.builtIn('REQUEST_PAYLOAD_TOO_LARGE'));
|
|
1898
|
-
return;
|
|
1899
|
-
}
|
|
1900
|
-
|
|
1901
|
-
if (
|
|
1902
|
-
this.engine.latestJoinResponse?.serverInfo?.version &&
|
|
1903
|
-
compareVersions(this.engine.latestJoinResponse?.serverInfo?.version, '1.8.0') < 0
|
|
1904
|
-
) {
|
|
1905
|
-
reject(RpcError.builtIn('UNSUPPORTED_SERVER'));
|
|
1906
|
-
return;
|
|
1907
|
-
}
|
|
1908
|
-
|
|
1909
|
-
const effectiveTimeout = Math.max(responseTimeout, minEffectiveTimeout);
|
|
1910
|
-
const id = crypto.randomUUID();
|
|
1911
|
-
await this.publishRpcRequest(destinationIdentity, id, method, payload, effectiveTimeout);
|
|
1912
|
-
|
|
1913
|
-
const ackTimeoutId = setTimeout(() => {
|
|
1914
|
-
this.pendingAcks.delete(id);
|
|
1915
|
-
reject(RpcError.builtIn('CONNECTION_TIMEOUT'));
|
|
1916
|
-
this.pendingResponses.delete(id);
|
|
1917
|
-
clearTimeout(responseTimeoutId);
|
|
1918
|
-
}, maxRoundTripLatency);
|
|
1919
|
-
|
|
1920
|
-
this.pendingAcks.set(id, {
|
|
1921
|
-
resolve: () => {
|
|
1922
|
-
clearTimeout(ackTimeoutId);
|
|
1923
|
-
},
|
|
1924
|
-
participantIdentity: destinationIdentity,
|
|
1925
|
-
});
|
|
1926
|
-
|
|
1927
|
-
const responseTimeoutId = setTimeout(() => {
|
|
1928
|
-
this.pendingResponses.delete(id);
|
|
1929
|
-
reject(RpcError.builtIn('RESPONSE_TIMEOUT'));
|
|
1930
|
-
}, responseTimeout);
|
|
1931
|
-
|
|
1932
|
-
this.pendingResponses.set(id, {
|
|
1933
|
-
resolve: (responsePayload: string | null, responseError: RpcError | null) => {
|
|
1934
|
-
clearTimeout(responseTimeoutId);
|
|
1935
|
-
if (this.pendingAcks.has(id)) {
|
|
1936
|
-
this.log.warn('RPC response received before ack', id);
|
|
1937
|
-
this.pendingAcks.delete(id);
|
|
1938
|
-
clearTimeout(ackTimeoutId);
|
|
1939
|
-
}
|
|
1940
|
-
|
|
1941
|
-
if (responseError) {
|
|
1942
|
-
reject(responseError);
|
|
1943
|
-
} else {
|
|
1944
|
-
resolve(responsePayload ?? '');
|
|
1945
|
-
}
|
|
1946
|
-
},
|
|
1947
|
-
participantIdentity: destinationIdentity,
|
|
1948
|
-
});
|
|
1854
|
+
performRpc(params: PerformRpcParams): TypedPromise<string, RpcError> {
|
|
1855
|
+
return this.rpcClientManager.performRpc(params).then(([_id, completionPromise]) => {
|
|
1856
|
+
return completionPromise;
|
|
1949
1857
|
});
|
|
1950
1858
|
}
|
|
1951
1859
|
|
|
@@ -1953,20 +1861,14 @@ export default class LocalParticipant extends Participant {
|
|
|
1953
1861
|
* @deprecated use `room.registerRpcMethod` instead
|
|
1954
1862
|
*/
|
|
1955
1863
|
registerRpcMethod(method: string, handler: (data: RpcInvocationData) => Promise<string>) {
|
|
1956
|
-
|
|
1957
|
-
this.log.warn(
|
|
1958
|
-
`you're overriding the RPC handler for method ${method}, in the future this will throw an error`,
|
|
1959
|
-
);
|
|
1960
|
-
}
|
|
1961
|
-
|
|
1962
|
-
this.rpcHandlers.set(method, handler);
|
|
1864
|
+
this.rpcServerManager.registerRpcMethod(method, handler);
|
|
1963
1865
|
}
|
|
1964
1866
|
|
|
1965
1867
|
/**
|
|
1966
1868
|
* @deprecated use `room.unregisterRpcMethod` instead
|
|
1967
1869
|
*/
|
|
1968
1870
|
unregisterRpcMethod(method: string) {
|
|
1969
|
-
this.
|
|
1871
|
+
this.rpcServerManager.unregisterRpcMethod(method);
|
|
1970
1872
|
}
|
|
1971
1873
|
|
|
1972
1874
|
/**
|
|
@@ -1997,72 +1899,6 @@ export default class LocalParticipant extends Participant {
|
|
|
1997
1899
|
}
|
|
1998
1900
|
}
|
|
1999
1901
|
|
|
2000
|
-
private handleIncomingRpcAck(requestId: string) {
|
|
2001
|
-
const handler = this.pendingAcks.get(requestId);
|
|
2002
|
-
if (handler) {
|
|
2003
|
-
handler.resolve();
|
|
2004
|
-
this.pendingAcks.delete(requestId);
|
|
2005
|
-
} else {
|
|
2006
|
-
console.error('Ack received for unexpected RPC request', requestId);
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
|
|
2010
|
-
private handleIncomingRpcResponse(
|
|
2011
|
-
requestId: string,
|
|
2012
|
-
payload: string | null,
|
|
2013
|
-
error: RpcError | null,
|
|
2014
|
-
) {
|
|
2015
|
-
const handler = this.pendingResponses.get(requestId);
|
|
2016
|
-
if (handler) {
|
|
2017
|
-
handler.resolve(payload, error);
|
|
2018
|
-
this.pendingResponses.delete(requestId);
|
|
2019
|
-
} else {
|
|
2020
|
-
console.error('Response received for unexpected RPC request', requestId);
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
|
|
2024
|
-
/** @internal */
|
|
2025
|
-
private async publishRpcRequest(
|
|
2026
|
-
destinationIdentity: string,
|
|
2027
|
-
requestId: string,
|
|
2028
|
-
method: string,
|
|
2029
|
-
payload: string,
|
|
2030
|
-
responseTimeout: number,
|
|
2031
|
-
) {
|
|
2032
|
-
const packet = new DataPacket({
|
|
2033
|
-
destinationIdentities: [destinationIdentity],
|
|
2034
|
-
kind: DataPacket_Kind.RELIABLE,
|
|
2035
|
-
value: {
|
|
2036
|
-
case: 'rpcRequest',
|
|
2037
|
-
value: new RpcRequest({
|
|
2038
|
-
id: requestId,
|
|
2039
|
-
method,
|
|
2040
|
-
payload,
|
|
2041
|
-
responseTimeoutMs: responseTimeout,
|
|
2042
|
-
version: 1,
|
|
2043
|
-
}),
|
|
2044
|
-
},
|
|
2045
|
-
});
|
|
2046
|
-
|
|
2047
|
-
await this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
|
|
2048
|
-
}
|
|
2049
|
-
|
|
2050
|
-
/** @internal */
|
|
2051
|
-
handleParticipantDisconnected(participantIdentity: string) {
|
|
2052
|
-
for (const [id, { participantIdentity: pendingIdentity }] of this.pendingAcks) {
|
|
2053
|
-
if (pendingIdentity === participantIdentity) {
|
|
2054
|
-
this.pendingAcks.delete(id);
|
|
2055
|
-
}
|
|
2056
|
-
}
|
|
2057
|
-
|
|
2058
|
-
for (const [id, { participantIdentity: pendingIdentity, resolve }] of this.pendingResponses) {
|
|
2059
|
-
if (pendingIdentity === participantIdentity) {
|
|
2060
|
-
resolve(null, RpcError.builtIn('RECIPIENT_DISCONNECTED'));
|
|
2061
|
-
this.pendingResponses.delete(id);
|
|
2062
|
-
}
|
|
2063
|
-
}
|
|
2064
|
-
}
|
|
2065
|
-
|
|
2066
1902
|
/** @internal */
|
|
2067
1903
|
setEnabledPublishCodecs(codecs: Codec[]) {
|
|
2068
1904
|
this.enabledPublishVideoCodecs = codecs.filter(
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from '@livekit/protocol';
|
|
7
7
|
import type { SignalClient } from '../../api/SignalClient';
|
|
8
8
|
import { DeferrableMap } from '../../utils/deferrable-map';
|
|
9
|
+
import { CLIENT_PROTOCOL_DEFAULT } from '../../version';
|
|
9
10
|
import RemoteDataTrack from '../data-track/RemoteDataTrack';
|
|
10
11
|
import type IncomingDataTrackManager from '../data-track/incoming/IncomingDataTrackManager';
|
|
11
12
|
import { DataTrackInfo } from '../data-track/types';
|
|
@@ -41,6 +42,11 @@ export default class RemoteParticipant extends Participant {
|
|
|
41
42
|
|
|
42
43
|
signalClient: SignalClient;
|
|
43
44
|
|
|
45
|
+
/** A version number indicating the set of features that the report participant's client supports.
|
|
46
|
+
* @internal
|
|
47
|
+
**/
|
|
48
|
+
clientProtocol: number;
|
|
49
|
+
|
|
44
50
|
private volumeMap: Map<Track.Source, number>;
|
|
45
51
|
|
|
46
52
|
private audioOutput?: AudioOutputOptions;
|
|
@@ -65,6 +71,7 @@ export default class RemoteParticipant extends Participant {
|
|
|
65
71
|
const info = DataTrackInfo.from(dti);
|
|
66
72
|
return new RemoteDataTrack(info, manager, { publisherIdentity: pi.identity });
|
|
67
73
|
}),
|
|
74
|
+
pi.clientProtocol,
|
|
68
75
|
);
|
|
69
76
|
}
|
|
70
77
|
|
|
@@ -87,6 +94,7 @@ export default class RemoteParticipant extends Participant {
|
|
|
87
94
|
loggerOptions?: LoggerOptions,
|
|
88
95
|
kind: ParticipantKind = ParticipantKind.STANDARD,
|
|
89
96
|
remoteDataTracks: Array<RemoteDataTrack> = [],
|
|
97
|
+
clientProtocol: number = CLIENT_PROTOCOL_DEFAULT,
|
|
90
98
|
) {
|
|
91
99
|
super(sid, identity || '', name, metadata, attributes, loggerOptions, kind);
|
|
92
100
|
this.signalClient = signalClient;
|
|
@@ -99,6 +107,7 @@ export default class RemoteParticipant extends Participant {
|
|
|
99
107
|
}),
|
|
100
108
|
);
|
|
101
109
|
this.volumeMap = new Map();
|
|
110
|
+
this.clientProtocol = clientProtocol;
|
|
102
111
|
}
|
|
103
112
|
|
|
104
113
|
protected addTrackPublication(publication: RemoteTrackPublication) {
|