livekit-client 2.22.3 → 2.23.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/README.md +35 -0
- package/dist/livekit-client.e2ee.worker.js +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +71 -8
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +1746 -547
- package/dist/livekit-client.esm.mjs.map +1 -1
- package/dist/livekit-client.fm.worker.js +1 -1
- package/dist/livekit-client.fm.worker.js.map +1 -1
- package/dist/livekit-client.fm.worker.mjs +2 -1
- package/dist/livekit-client.fm.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/api/SignalClient.d.ts +4 -2
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/api/WebSocketStream.d.ts +1 -0
- package/dist/src/api/WebSocketStream.d.ts.map +1 -1
- package/dist/src/api/utils.d.ts +1 -1
- package/dist/src/api/utils.d.ts.map +1 -1
- package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/e2ee/worker/naluUtils.d.ts +12 -1
- package/dist/src/e2ee/worker/naluUtils.d.ts.map +1 -1
- package/dist/src/index.d.ts +2 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/options.d.ts +14 -0
- package/dist/src/options.d.ts.map +1 -1
- package/dist/src/room/DefaultReconnectPolicy.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +100 -7
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +16 -0
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +54 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/data-channel/DataChannelManager.d.ts +9 -8
- package/dist/src/room/data-channel/DataChannelManager.d.ts.map +1 -1
- package/dist/src/room/data-channel/FlowControlledDataChannel.d.ts +25 -12
- package/dist/src/room/data-channel/FlowControlledDataChannel.d.ts.map +1 -1
- package/dist/src/room/data-channel/LossyDataChannel.d.ts.map +1 -1
- package/dist/src/room/data-channel/ReliableDataChannel.d.ts.map +1 -1
- package/dist/src/room/data-stream/incoming/IncomingDataStreamManager.d.ts.map +1 -1
- package/dist/src/room/defaults.d.ts.map +1 -1
- package/dist/src/room/errors.d.ts +18 -0
- package/dist/src/room/errors.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +3 -2
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +4 -0
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/Participant.d.ts +1 -1
- package/dist/src/room/participant/Participant.d.ts.map +1 -1
- package/dist/src/room/participant/publishUtils.d.ts.map +1 -1
- package/dist/src/room/rpc/client/RpcClientManager.d.ts.map +1 -1
- package/dist/src/room/rpc/utils.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts +24 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalTrack.d.ts +18 -0
- package/dist/src/room/track/LocalTrack.d.ts.map +1 -1
- package/dist/src/room/track/LocalVideoTrack.d.ts +9 -0
- package/dist/src/room/track/LocalVideoTrack.d.ts.map +1 -1
- package/dist/src/room/track/RemoteAudioTrack.d.ts +6 -0
- package/dist/src/room/track/RemoteAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/processor/types.d.ts +11 -0
- package/dist/src/room/track/processor/types.d.ts.map +1 -1
- package/dist/src/room/track/utils.d.ts +13 -0
- package/dist/src/room/track/utils.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts +60 -1
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/src/test/compressionStreamStubs.d.ts +12 -0
- package/dist/src/test/compressionStreamStubs.d.ts.map +1 -0
- package/dist/ts4.2/api/SignalClient.d.ts +187 -185
- package/dist/ts4.2/api/SignalClientStateMachine.d.ts +85 -85
- package/dist/ts4.2/api/WebSocketStream.d.ts +34 -33
- package/dist/ts4.2/api/utils.d.ts +9 -9
- package/dist/ts4.2/connectionHelper/ConnectionCheck.d.ts +30 -30
- package/dist/ts4.2/connectionHelper/checks/Checker.d.ts +62 -62
- package/dist/ts4.2/connectionHelper/checks/cloudRegion.d.ts +18 -18
- package/dist/ts4.2/connectionHelper/checks/connectionProtocol.d.ts +20 -20
- package/dist/ts4.2/connectionHelper/checks/publishAudio.d.ts +6 -6
- package/dist/ts4.2/connectionHelper/checks/publishVideo.d.ts +7 -7
- package/dist/ts4.2/connectionHelper/checks/reconnect.d.ts +6 -6
- package/dist/ts4.2/connectionHelper/checks/turn.d.ts +6 -6
- package/dist/ts4.2/connectionHelper/checks/webrtc.d.ts +6 -6
- package/dist/ts4.2/connectionHelper/checks/websocket.d.ts +6 -6
- package/dist/ts4.2/e2ee/E2eeManager.d.ts +111 -111
- package/dist/ts4.2/e2ee/KeyProvider.d.ts +54 -54
- package/dist/ts4.2/e2ee/constants.d.ts +21 -21
- package/dist/ts4.2/e2ee/errors.d.ts +12 -12
- package/dist/ts4.2/e2ee/events.d.ts +39 -39
- package/dist/ts4.2/e2ee/index.d.ts +6 -6
- package/dist/ts4.2/e2ee/types.d.ts +231 -231
- package/dist/ts4.2/e2ee/utils.d.ts +32 -32
- package/dist/ts4.2/e2ee/worker/DataCryptor.d.ts +16 -16
- package/dist/ts4.2/e2ee/worker/ErrorRateLimiter.d.ts +21 -21
- package/dist/ts4.2/e2ee/worker/FrameCryptor.d.ts +209 -209
- package/dist/ts4.2/e2ee/worker/ParticipantKeyHandler.d.ts +81 -84
- package/dist/ts4.2/e2ee/worker/e2ee.worker.d.ts +2 -2
- package/dist/ts4.2/e2ee/worker/naluUtils.d.ts +39 -28
- package/dist/ts4.2/e2ee/worker/sifPayload.d.ts +23 -23
- package/dist/ts4.2/frameMetadata/FrameMetadataManager.d.ts +53 -53
- package/dist/ts4.2/frameMetadata/frameMetadata.d.ts +33 -33
- package/dist/ts4.2/frameMetadata/types.d.ts +62 -62
- package/dist/ts4.2/frameMetadata/utils.d.ts +9 -9
- package/dist/ts4.2/frameMetadata/worker/frameMetadata.worker.d.ts +2 -2
- package/dist/ts4.2/index.d.ts +76 -76
- package/dist/ts4.2/logger.d.ts +66 -66
- package/dist/ts4.2/options.d.ts +163 -149
- package/dist/ts4.2/room/BackOffStrategy.d.ts +27 -27
- package/dist/ts4.2/room/DefaultReconnectPolicy.d.ts +8 -8
- package/dist/ts4.2/room/DeviceManager.d.ts +12 -12
- package/dist/ts4.2/room/PCTransport.d.ts +268 -175
- package/dist/ts4.2/room/PCTransportManager.d.ts +77 -77
- package/dist/ts4.2/room/RTCEngine.d.ts +277 -262
- package/dist/ts4.2/room/ReconnectPolicy.d.ts +24 -24
- package/dist/ts4.2/room/RegionUrlProvider.d.ts +36 -36
- package/dist/ts4.2/room/Room.d.ts +407 -365
- package/dist/ts4.2/room/attribute-typings.d.ts +35 -35
- package/dist/ts4.2/room/data-channel/DataChannelManager.d.ts +63 -62
- package/dist/ts4.2/room/data-channel/FlowControlledDataChannel.d.ts +107 -95
- package/dist/ts4.2/room/data-channel/LossyDataChannel.d.ts +41 -41
- package/dist/ts4.2/room/data-channel/ReliableDataChannel.d.ts +57 -57
- package/dist/ts4.2/room/data-channel/types.d.ts +12 -12
- package/dist/ts4.2/room/data-stream/compression.d.ts +49 -49
- package/dist/ts4.2/room/data-stream/constants.d.ts +18 -18
- package/dist/ts4.2/room/data-stream/incoming/IncomingDataStreamManager.d.ts +29 -29
- package/dist/ts4.2/room/data-stream/incoming/StreamReader.d.ts +80 -80
- package/dist/ts4.2/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts +73 -73
- package/dist/ts4.2/room/data-stream/outgoing/StreamWriter.d.ts +16 -16
- package/dist/ts4.2/room/data-stream/outgoing/header-utils.d.ts +18 -18
- package/dist/ts4.2/room/data-track/LocalDataTrack.d.ts +79 -80
- package/dist/ts4.2/room/data-track/RemoteDataTrack.d.ts +50 -50
- package/dist/ts4.2/room/data-track/depacketizer.d.ts +59 -59
- package/dist/ts4.2/room/data-track/frame.d.ts +22 -22
- package/dist/ts4.2/room/data-track/handle.d.ts +27 -27
- package/dist/ts4.2/room/data-track/incoming/IncomingDataTrackManager.d.ts +124 -124
- package/dist/ts4.2/room/data-track/incoming/errors.d.ts +24 -24
- package/dist/ts4.2/room/data-track/incoming/pipeline.d.ts +41 -41
- package/dist/ts4.2/room/data-track/incoming/types.d.ts +20 -20
- package/dist/ts4.2/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +126 -126
- package/dist/ts4.2/room/data-track/outgoing/errors.d.ts +74 -74
- package/dist/ts4.2/room/data-track/outgoing/pipeline.d.ts +23 -23
- package/dist/ts4.2/room/data-track/outgoing/types.d.ts +48 -48
- package/dist/ts4.2/room/data-track/packet/constants.d.ts +20 -20
- package/dist/ts4.2/room/data-track/packet/errors.d.ts +40 -40
- package/dist/ts4.2/room/data-track/packet/extensions.d.ts +69 -69
- package/dist/ts4.2/room/data-track/packet/index.d.ts +98 -98
- package/dist/ts4.2/room/data-track/packet/serializable.d.ts +13 -13
- package/dist/ts4.2/room/data-track/packetizer.d.ts +43 -43
- package/dist/ts4.2/room/data-track/track-interfaces.d.ts +23 -23
- package/dist/ts4.2/room/data-track/types.d.ts +22 -22
- package/dist/ts4.2/room/data-track/utils.d.ts +60 -60
- package/dist/ts4.2/room/debounce.d.ts +11 -11
- package/dist/ts4.2/room/defaults.d.ts +9 -9
- package/dist/ts4.2/room/errors.d.ts +180 -162
- package/dist/ts4.2/room/events.d.ts +638 -637
- package/dist/ts4.2/room/participant/LocalParticipant.d.ts +291 -287
- package/dist/ts4.2/room/participant/Participant.d.ts +142 -144
- package/dist/ts4.2/room/participant/ParticipantTrackPermission.d.ts +26 -26
- package/dist/ts4.2/room/participant/RemoteParticipant.d.ts +85 -86
- package/dist/ts4.2/room/participant/publishUtils.d.ts +53 -53
- package/dist/ts4.2/room/rpc/client/RpcClientManager.d.ts +43 -43
- package/dist/ts4.2/room/rpc/client/events.d.ts +8 -8
- package/dist/ts4.2/room/rpc/index.d.ts +7 -7
- package/dist/ts4.2/room/rpc/server/RpcServerManager.d.ts +44 -44
- package/dist/ts4.2/room/rpc/server/events.d.ts +8 -8
- package/dist/ts4.2/room/rpc/utils.d.ts +131 -131
- package/dist/ts4.2/room/stats.d.ts +71 -71
- package/dist/ts4.2/room/statsSummary.d.ts +13 -13
- package/dist/ts4.2/room/timers.d.ts +12 -12
- package/dist/ts4.2/room/token-source/TokenSource.d.ts +82 -82
- package/dist/ts4.2/room/token-source/types.d.ts +70 -70
- package/dist/ts4.2/room/token-source/utils.d.ts +8 -8
- package/dist/ts4.2/room/track/FrameMetadataExtractor.d.ts +19 -19
- package/dist/ts4.2/room/track/LocalAudioTrack.d.ts +62 -42
- package/dist/ts4.2/room/track/LocalTrack.d.ts +143 -125
- package/dist/ts4.2/room/track/LocalTrackPublication.d.ts +42 -42
- package/dist/ts4.2/room/track/LocalVideoTrack.d.ts +109 -100
- package/dist/ts4.2/room/track/RemoteAudioTrack.d.ts +61 -55
- package/dist/ts4.2/room/track/RemoteTrack.d.ts +38 -38
- package/dist/ts4.2/room/track/RemoteTrackPublication.d.ts +72 -75
- package/dist/ts4.2/room/track/RemoteVideoTrack.d.ts +73 -76
- package/dist/ts4.2/room/track/Track.d.ts +156 -166
- package/dist/ts4.2/room/track/TrackPublication.d.ts +75 -81
- package/dist/ts4.2/room/track/create.d.ts +25 -25
- package/dist/ts4.2/room/track/facingMode.d.ts +41 -41
- package/dist/ts4.2/room/track/options.d.ts +403 -403
- package/dist/ts4.2/room/track/processor/types.d.ts +42 -31
- package/dist/ts4.2/room/track/record.d.ts +13 -13
- package/dist/ts4.2/room/track/types.d.ts +28 -28
- package/dist/ts4.2/room/track/utils.d.ts +60 -47
- package/dist/ts4.2/room/types.d.ts +127 -127
- package/dist/ts4.2/room/utils.d.ts +273 -214
- package/dist/ts4.2/test/MockMediaStreamTrack.d.ts +26 -26
- package/dist/ts4.2/test/compressionStreamStubs.d.ts +12 -0
- package/dist/ts4.2/test/mocks.d.ts +12 -12
- package/dist/ts4.2/test/promiseState.d.ts +12 -12
- package/dist/ts4.2/test/signalToken.d.ts +26 -26
- package/dist/ts4.2/type-polyfills/non-shared-typed-arrays.d.ts +2 -2
- package/dist/ts4.2/utils/AsyncQueue.d.ts +23 -23
- package/dist/ts4.2/utils/TypedPromise.d.ts +17 -17
- package/dist/ts4.2/utils/abort-signal-polyfill.d.ts +13 -13
- package/dist/ts4.2/utils/browserParser.d.ts +13 -13
- package/dist/ts4.2/utils/camelToSnakeCase.d.ts +8 -8
- package/dist/ts4.2/utils/cloneDeep.d.ts +2 -2
- package/dist/ts4.2/utils/dataPacketBuffer.d.ts +34 -34
- package/dist/ts4.2/utils/deferrable-map.d.ts +32 -32
- package/dist/ts4.2/utils/machineInspector.d.ts +54 -54
- package/dist/ts4.2/utils/serializer.d.ts +48 -48
- package/dist/ts4.2/utils/subscribeToEvents.d.ts +15 -15
- package/dist/ts4.2/utils/ttlmap.d.ts +20 -20
- package/dist/ts4.2/version.d.ts +15 -15
- package/package.json +5 -4
- package/src/api/SignalClient.e2e.test.ts +1 -3
- package/src/api/SignalClient.test.ts +394 -10
- package/src/api/SignalClient.ts +132 -76
- package/src/api/WebSocketStream.test.ts +11 -0
- package/src/api/WebSocketStream.ts +22 -1
- package/src/api/utils.ts +1 -1
- package/src/e2ee/E2eeManager.test.ts +43 -0
- package/src/e2ee/E2eeManager.ts +6 -2
- package/src/e2ee/worker/FrameCryptor.test.ts +212 -90
- package/src/e2ee/worker/FrameCryptor.ts +21 -4
- package/src/e2ee/worker/naluUtils.test.ts +123 -0
- package/src/e2ee/worker/naluUtils.ts +57 -2
- package/src/index.ts +2 -0
- package/src/options.ts +16 -0
- package/src/room/DefaultReconnectPolicy.test.ts +58 -0
- package/src/room/DefaultReconnectPolicy.ts +14 -2
- package/src/room/PCTransport.test.ts +327 -9
- package/src/room/PCTransport.ts +339 -36
- package/src/room/PCTransportManager.ts +3 -1
- package/src/room/RTCEngine.test.ts +318 -2
- package/src/room/RTCEngine.ts +126 -12
- package/src/room/Room.test.ts +148 -6
- package/src/room/Room.ts +312 -80
- package/src/room/data-channel/DataChannelManager.test.ts +24 -7
- package/src/room/data-channel/DataChannelManager.ts +43 -38
- package/src/room/data-channel/FlowControlledDataChannel.test.ts +60 -18
- package/src/room/data-channel/FlowControlledDataChannel.ts +40 -22
- package/src/room/data-channel/LossyDataChannel.test.ts +38 -0
- package/src/room/data-channel/LossyDataChannel.ts +10 -1
- package/src/room/data-channel/ReliableDataChannel.test.ts +72 -0
- package/src/room/data-channel/ReliableDataChannel.ts +16 -5
- package/src/room/data-stream/incoming/IncomingDataStreamManager.test.ts +47 -20
- package/src/room/data-stream/incoming/IncomingDataStreamManager.ts +16 -5
- package/src/room/data-stream/outgoing/OutgoingDataStreamManager.test.ts +60 -39
- package/src/room/data-stream/outgoing/OutgoingDataStreamManager.ts +4 -4
- package/src/room/defaults.ts +1 -0
- package/src/room/errors.test.ts +36 -0
- package/src/room/errors.ts +27 -0
- package/src/room/events.ts +2 -1
- package/src/room/participant/LocalParticipant.test.ts +136 -1
- package/src/room/participant/LocalParticipant.ts +66 -17
- package/src/room/participant/Participant.ts +6 -3
- package/src/room/participant/publishUtils.ts +0 -19
- package/src/room/participant/restartOnDefaultAudioDevice.test.ts +177 -0
- package/src/room/rpc/client/RpcClientManager.test.ts +51 -0
- package/src/room/rpc/client/RpcClientManager.ts +32 -15
- package/src/room/rpc/utils.test.ts +32 -0
- package/src/room/rpc/utils.ts +7 -0
- package/src/room/track/LocalAudioTrack.ts +101 -10
- package/src/room/track/LocalTrack.ts +87 -19
- package/src/room/track/LocalVideoTrack.ts +17 -3
- package/src/room/track/RemoteAudioTrack.ts +59 -14
- package/src/room/track/RemoteVideoTrack.test.ts +210 -0
- package/src/room/track/RemoteVideoTrack.ts +29 -3
- package/src/room/track/processor/types.ts +11 -0
- package/src/room/track/utils.test.ts +206 -2
- package/src/room/track/utils.ts +117 -5
- package/src/room/utils.test.ts +250 -0
- package/src/room/utils.ts +152 -19
- package/src/test/compressionStreamStubs.ts +53 -0
package/dist/ts4.2/version.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
export declare const version: string;
|
|
2
|
-
export declare const protocolVersion = 17;
|
|
3
|
-
/** Initial client protocol. */
|
|
4
|
-
export declare const CLIENT_PROTOCOL_DEFAULT = 0;
|
|
5
|
-
/** Replaces RPC v1 protocol with a v2 data streams based one to support unlimited request /
|
|
6
|
-
* response payload length. */
|
|
7
|
-
export declare const CLIENT_PROTOCOL_DATA_STREAM_RPC = 1;
|
|
8
|
-
/** "Data streams v2": the client knows how to receive a single-packet data stream (a stream whose
|
|
9
|
-
* entire payload is smuggled into the header packet, with no chunk/trailer packets). Senders only
|
|
10
|
-
* use the single-packet optimization when the recipient advertises at least this protocol. */
|
|
11
|
-
export declare const CLIENT_PROTOCOL_DATA_STREAM_V2 = 2;
|
|
12
|
-
/** The client protocol version indicates what level of support that the client has for
|
|
13
|
-
* client <-> client api interactions. */
|
|
14
|
-
export declare const clientProtocol = 2;
|
|
15
|
-
//# sourceMappingURL=version.d.ts.map
|
|
1
|
+
export declare const version: string;
|
|
2
|
+
export declare const protocolVersion = 17;
|
|
3
|
+
/** Initial client protocol. */
|
|
4
|
+
export declare const CLIENT_PROTOCOL_DEFAULT = 0;
|
|
5
|
+
/** Replaces RPC v1 protocol with a v2 data streams based one to support unlimited request /
|
|
6
|
+
* response payload length. */
|
|
7
|
+
export declare const CLIENT_PROTOCOL_DATA_STREAM_RPC = 1;
|
|
8
|
+
/** "Data streams v2": the client knows how to receive a single-packet data stream (a stream whose
|
|
9
|
+
* entire payload is smuggled into the header packet, with no chunk/trailer packets). Senders only
|
|
10
|
+
* use the single-packet optimization when the recipient advertises at least this protocol. */
|
|
11
|
+
export declare const CLIENT_PROTOCOL_DATA_STREAM_V2 = 2;
|
|
12
|
+
/** The client protocol version indicates what level of support that the client has for
|
|
13
|
+
* client <-> client api interactions. */
|
|
14
|
+
export declare const clientProtocol = 2;
|
|
15
|
+
//# sourceMappingURL=version.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "livekit-client",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.23.0",
|
|
4
4
|
"description": "JavaScript/TypeScript client SDK for LiveKit",
|
|
5
5
|
"main": "./dist/livekit-client.umd.js",
|
|
6
6
|
"unpkg": "./dist/livekit-client.umd.js",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"license": "Apache-2.0",
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"@livekit/mutex": "1.1.1",
|
|
53
|
-
"@livekit/protocol": "1.
|
|
53
|
+
"@livekit/protocol": "1.52.1",
|
|
54
54
|
"events": "^3.3.0",
|
|
55
55
|
"jose": "^6.1.0",
|
|
56
56
|
"loglevel": "^1.9.2",
|
|
@@ -85,9 +85,10 @@
|
|
|
85
85
|
"@types/ua-parser-js": "0.7.39",
|
|
86
86
|
"@typescript-eslint/eslint-plugin": "8.64.0",
|
|
87
87
|
"@typescript-eslint/parser": "8.64.0",
|
|
88
|
+
"@typescript/native": "npm:typescript@^7.0.2",
|
|
88
89
|
"@vitest/browser": "^4.1.10",
|
|
89
90
|
"@vitest/browser-playwright": "^4.1.10",
|
|
90
|
-
"downlevel-dts": "^0.
|
|
91
|
+
"@nbilyk/downlevel-dts": "^0.15.2",
|
|
91
92
|
"eslint": "10.7.0",
|
|
92
93
|
"eslint-config-airbnb-extended": "^2.3.2",
|
|
93
94
|
"eslint-config-prettier": "10.1.8",
|
|
@@ -113,7 +114,7 @@
|
|
|
113
114
|
"tsx": "^4.21.0",
|
|
114
115
|
"typedoc": "0.28.20",
|
|
115
116
|
"typedoc-plugin-no-inherit": "1.6.1",
|
|
116
|
-
"typescript": "
|
|
117
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
117
118
|
"typescript-eslint": "^8.47.0",
|
|
118
119
|
"vite": "8.1.5",
|
|
119
120
|
"vitest": "^4.1.10"
|
|
@@ -174,9 +174,7 @@ describe.skipIf(!!unavailable)('SignalClient e2e', () => {
|
|
|
174
174
|
|
|
175
175
|
it('rejects a reconnect when a leave arrives as the first message', async () => {
|
|
176
176
|
// Reconnecting into a room that sends leave-first exercises the client's
|
|
177
|
-
// first-message validation while in RECONNECTING
|
|
178
|
-
// doesn't rely on the mock detecting reconnect, which v1 hides inside the
|
|
179
|
-
// gzipped join_request the mock ignores).
|
|
177
|
+
// first-message validation while in RECONNECTING.
|
|
180
178
|
await join('happy');
|
|
181
179
|
const token = await createToken({ signal: 'leave_first_message' });
|
|
182
180
|
const err = await client.reconnect(serverUrl, token, 'RM_session').then(
|
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
WrappedJoinRequest_Compression,
|
|
12
12
|
} from '@livekit/protocol';
|
|
13
13
|
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
14
|
+
import type { Mutex } from '@livekit/mutex';
|
|
14
15
|
import { ConnectionError, ConnectionErrorReason } from '../room/errors';
|
|
15
16
|
import CriticalTimers from '../room/timers';
|
|
17
|
+
import { Future } from '../room/utils';
|
|
16
18
|
import { SignalClient, SignalConnectionState } from './SignalClient';
|
|
17
19
|
import type { WebSocketCloseInfo, WebSocketConnection } from './WebSocketStream';
|
|
18
20
|
import { WebSocketStream } from './WebSocketStream';
|
|
@@ -147,6 +149,167 @@ describe('SignalClient.connect', () => {
|
|
|
147
149
|
return JoinRequest.fromBinary(bytes);
|
|
148
150
|
}
|
|
149
151
|
|
|
152
|
+
describe('Cancelled connection attempts', () => {
|
|
153
|
+
it.each(['before join', 'while waiting for the connection lock'])(
|
|
154
|
+
'does not open a transport when aborted %s',
|
|
155
|
+
async (when) => {
|
|
156
|
+
const abortController = new AbortController();
|
|
157
|
+
const internals = signalClient as unknown as { connectionLock: Mutex };
|
|
158
|
+
const unlock = await internals.connectionLock.lock();
|
|
159
|
+
mockWebSocketStream({
|
|
160
|
+
connection: createMockConnection(
|
|
161
|
+
createMockReadableStream([createSignalResponse('join', createJoinResponse())]),
|
|
162
|
+
),
|
|
163
|
+
});
|
|
164
|
+
if (when === 'before join') abortController.abort();
|
|
165
|
+
const joining = signalClient.join(
|
|
166
|
+
'wss://test.livekit.io',
|
|
167
|
+
'test-token',
|
|
168
|
+
defaultOptions,
|
|
169
|
+
abortController.signal,
|
|
170
|
+
);
|
|
171
|
+
abortController.abort();
|
|
172
|
+
unlock();
|
|
173
|
+
|
|
174
|
+
try {
|
|
175
|
+
await expect(joining).rejects.toMatchObject({ reason: ConnectionErrorReason.Cancelled });
|
|
176
|
+
expect(WebSocketStream).not.toHaveBeenCalled();
|
|
177
|
+
} finally {
|
|
178
|
+
await signalClient.close();
|
|
179
|
+
vi.mocked(WebSocketStream).mockReset();
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
it('does not replace a transport when aborted during its teardown', async () => {
|
|
185
|
+
const abortController = new AbortController();
|
|
186
|
+
const internals = signalClient as unknown as {
|
|
187
|
+
connectionLock: Mutex;
|
|
188
|
+
teardownTransport: (reason: string) => Promise<void>;
|
|
189
|
+
};
|
|
190
|
+
const teardownStarted = new Future<void, Error>();
|
|
191
|
+
const finishTeardown = new Future<void, Error>();
|
|
192
|
+
vi.spyOn(internals, 'teardownTransport').mockImplementationOnce(async () => {
|
|
193
|
+
teardownStarted.resolve?.();
|
|
194
|
+
await finishTeardown.promise;
|
|
195
|
+
});
|
|
196
|
+
signalClient.ws = {
|
|
197
|
+
close: () => {},
|
|
198
|
+
closed: Promise.resolve({ closeCode: 1000, reason: '' }),
|
|
199
|
+
} as WebSocketStream;
|
|
200
|
+
mockWebSocketStream({
|
|
201
|
+
connection: createMockConnection(
|
|
202
|
+
createMockReadableStream([createSignalResponse('join', createJoinResponse())]),
|
|
203
|
+
),
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const joining = signalClient.join(
|
|
207
|
+
'wss://test.livekit.io',
|
|
208
|
+
'test-token',
|
|
209
|
+
defaultOptions,
|
|
210
|
+
abortController.signal,
|
|
211
|
+
);
|
|
212
|
+
const cancelled = expect(joining).rejects.toMatchObject({
|
|
213
|
+
reason: ConnectionErrorReason.Cancelled,
|
|
214
|
+
});
|
|
215
|
+
await teardownStarted.promise;
|
|
216
|
+
abortController.abort();
|
|
217
|
+
finishTeardown.resolve?.();
|
|
218
|
+
await cancelled;
|
|
219
|
+
// The rejection can settle before the transport replacement resumes.
|
|
220
|
+
const unlock = await internals.connectionLock.lock();
|
|
221
|
+
unlock();
|
|
222
|
+
|
|
223
|
+
try {
|
|
224
|
+
expect(WebSocketStream).not.toHaveBeenCalled();
|
|
225
|
+
} finally {
|
|
226
|
+
await signalClient.close();
|
|
227
|
+
vi.mocked(WebSocketStream).mockReset();
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
it('does not validate the url when aborted while the websocket is opening', async () => {
|
|
231
|
+
const abortController = new AbortController();
|
|
232
|
+
const internals = signalClient as unknown as { connectionLock: Mutex };
|
|
233
|
+
const opened = new Future<WebSocketConnection, Error>();
|
|
234
|
+
opened.promise.catch(() => {});
|
|
235
|
+
mockWebSocketStream({ opened: opened.promise, readyState: 0 });
|
|
236
|
+
vi.mocked(global.fetch).mockClear();
|
|
237
|
+
|
|
238
|
+
const joining = signalClient.join(
|
|
239
|
+
'wss://test.livekit.io',
|
|
240
|
+
'test-token',
|
|
241
|
+
defaultOptions,
|
|
242
|
+
abortController.signal,
|
|
243
|
+
);
|
|
244
|
+
const cancelled = expect(joining).rejects.toMatchObject({
|
|
245
|
+
reason: ConnectionErrorReason.Cancelled,
|
|
246
|
+
});
|
|
247
|
+
await vi.waitFor(() => expect(WebSocketStream).toHaveBeenCalled());
|
|
248
|
+
abortController.abort();
|
|
249
|
+
opened.reject?.(new Error('closed by abort'));
|
|
250
|
+
await cancelled;
|
|
251
|
+
// let the attempt's continuation run to completion
|
|
252
|
+
const unlock = await internals.connectionLock.lock();
|
|
253
|
+
unlock();
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
expect(global.fetch).not.toHaveBeenCalled();
|
|
257
|
+
} finally {
|
|
258
|
+
await signalClient.close();
|
|
259
|
+
vi.mocked(WebSocketStream).mockReset();
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it('does not report a join that arrives after the attempt was aborted', async () => {
|
|
264
|
+
const abortController = new AbortController();
|
|
265
|
+
const internals = signalClient as unknown as { connectionLock: Mutex };
|
|
266
|
+
let enqueue: ((chunk: ArrayBuffer) => void) | undefined;
|
|
267
|
+
const readable = new ReadableStream<ArrayBuffer>({
|
|
268
|
+
start(controller) {
|
|
269
|
+
enqueue = (chunk) => controller.enqueue(chunk);
|
|
270
|
+
},
|
|
271
|
+
});
|
|
272
|
+
const writerReady = new Future<void, Error>();
|
|
273
|
+
const writable = new WritableStream();
|
|
274
|
+
const getWriter = writable.getWriter.bind(writable);
|
|
275
|
+
writable.getWriter = () => {
|
|
276
|
+
const writer = getWriter();
|
|
277
|
+
writerReady.resolve?.();
|
|
278
|
+
return writer;
|
|
279
|
+
};
|
|
280
|
+
mockWebSocketStream({
|
|
281
|
+
connection: { readable, writable, protocol: '', extensions: '' },
|
|
282
|
+
});
|
|
283
|
+
const onJoined = vi.fn();
|
|
284
|
+
signalClient.onJoined = onJoined;
|
|
285
|
+
|
|
286
|
+
const joining = signalClient.join(
|
|
287
|
+
'wss://test.livekit.io',
|
|
288
|
+
'test-token',
|
|
289
|
+
defaultOptions,
|
|
290
|
+
abortController.signal,
|
|
291
|
+
);
|
|
292
|
+
const cancelled = expect(joining).rejects.toMatchObject({
|
|
293
|
+
reason: ConnectionErrorReason.Cancelled,
|
|
294
|
+
});
|
|
295
|
+
await writerReady.promise;
|
|
296
|
+
abortController.abort();
|
|
297
|
+
enqueue?.(
|
|
298
|
+
createSignalResponse('join', createJoinResponse()).toBinary().buffer as ArrayBuffer,
|
|
299
|
+
);
|
|
300
|
+
await cancelled;
|
|
301
|
+
const unlock = await internals.connectionLock.lock();
|
|
302
|
+
unlock();
|
|
303
|
+
|
|
304
|
+
try {
|
|
305
|
+
expect(onJoined).not.toHaveBeenCalled();
|
|
306
|
+
} finally {
|
|
307
|
+
await signalClient.close();
|
|
308
|
+
vi.mocked(WebSocketStream).mockReset();
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
|
|
150
313
|
describe('Happy Path - Initial Join', () => {
|
|
151
314
|
it('should successfully connect and receive join response', async () => {
|
|
152
315
|
const joinResponse = createJoinResponse();
|
|
@@ -162,6 +325,17 @@ describe('SignalClient.connect', () => {
|
|
|
162
325
|
expect(signalClient.currentState).toBe(SignalConnectionState.CONNECTED);
|
|
163
326
|
});
|
|
164
327
|
|
|
328
|
+
it('releases the connection lock when the url is malformed', async () => {
|
|
329
|
+
await expect(signalClient.join('not a url', 'test-token', defaultOptions)).rejects.toThrow();
|
|
330
|
+
|
|
331
|
+
const joinResponse = createJoinResponse();
|
|
332
|
+
const mockReadable = createMockReadableStream([createSignalResponse('join', joinResponse)]);
|
|
333
|
+
mockWebSocketStream({ connection: createMockConnection(mockReadable) });
|
|
334
|
+
|
|
335
|
+
const result = await signalClient.join('wss://test.livekit.io', 'test-token', defaultOptions);
|
|
336
|
+
expect(result).toEqual(joinResponse);
|
|
337
|
+
});
|
|
338
|
+
|
|
165
339
|
it('does not advertise packet trailer capability by default', async () => {
|
|
166
340
|
const joinResponse = createJoinResponse();
|
|
167
341
|
const signalResponse = createSignalResponse('join', joinResponse);
|
|
@@ -206,6 +380,152 @@ describe('SignalClient.connect', () => {
|
|
|
206
380
|
ClientInfo_Capability.CAP_PACKET_TRAILER,
|
|
207
381
|
]);
|
|
208
382
|
});
|
|
383
|
+
|
|
384
|
+
it('does not request full ICE by default', async () => {
|
|
385
|
+
const joinResponse = createJoinResponse();
|
|
386
|
+
const signalResponse = createSignalResponse('join', joinResponse);
|
|
387
|
+
const mockReadable = createMockReadableStream([signalResponse]);
|
|
388
|
+
const mockConnection = createMockConnection(mockReadable);
|
|
389
|
+
let capturedUrl = '';
|
|
390
|
+
|
|
391
|
+
mockWebSocketStream({
|
|
392
|
+
connection: mockConnection,
|
|
393
|
+
onUrl: (url) => {
|
|
394
|
+
capturedUrl = url;
|
|
395
|
+
},
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
await signalClient.join('wss://test.livekit.io', 'test-token', defaultOptions);
|
|
399
|
+
|
|
400
|
+
const joinRequest = await decodeJoinRequestFromUrl(capturedUrl);
|
|
401
|
+
expect(joinRequest.connectionSettings?.disableIceLite).toBe(false);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
it('requests full ICE in the join request when disableIceLite is set', async () => {
|
|
405
|
+
const joinResponse = createJoinResponse();
|
|
406
|
+
const signalResponse = createSignalResponse('join', joinResponse);
|
|
407
|
+
const mockReadable = createMockReadableStream([signalResponse]);
|
|
408
|
+
const mockConnection = createMockConnection(mockReadable);
|
|
409
|
+
let capturedUrl = '';
|
|
410
|
+
|
|
411
|
+
mockWebSocketStream({
|
|
412
|
+
connection: mockConnection,
|
|
413
|
+
onUrl: (url) => {
|
|
414
|
+
capturedUrl = url;
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
await signalClient.join('wss://test.livekit.io', 'test-token', {
|
|
419
|
+
...defaultOptions,
|
|
420
|
+
disableIceLite: true,
|
|
421
|
+
});
|
|
422
|
+
|
|
423
|
+
const joinRequest = await decodeJoinRequestFromUrl(capturedUrl);
|
|
424
|
+
expect(joinRequest.connectionSettings?.disableIceLite).toBe(true);
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
it('requests full ICE on the v0 path when disableIceLite is set', async () => {
|
|
428
|
+
const joinResponse = createJoinResponse();
|
|
429
|
+
const signalResponse = createSignalResponse('join', joinResponse);
|
|
430
|
+
const mockReadable = createMockReadableStream([signalResponse]);
|
|
431
|
+
const mockConnection = createMockConnection(mockReadable);
|
|
432
|
+
let capturedUrl = '';
|
|
433
|
+
|
|
434
|
+
mockWebSocketStream({
|
|
435
|
+
connection: mockConnection,
|
|
436
|
+
onUrl: (url) => {
|
|
437
|
+
capturedUrl = url;
|
|
438
|
+
},
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
await signalClient.join(
|
|
442
|
+
'wss://test.livekit.io',
|
|
443
|
+
'test-token',
|
|
444
|
+
{ ...defaultOptions, disableIceLite: true },
|
|
445
|
+
undefined,
|
|
446
|
+
true,
|
|
447
|
+
);
|
|
448
|
+
|
|
449
|
+
expect(new URL(capturedUrl).searchParams.get('disable_ice_lite')).toBe('1');
|
|
450
|
+
});
|
|
451
|
+
|
|
452
|
+
it('leaves subscriberAllowPause unset by default so the server default applies', async () => {
|
|
453
|
+
const joinResponse = createJoinResponse();
|
|
454
|
+
const signalResponse = createSignalResponse('join', joinResponse);
|
|
455
|
+
const mockReadable = createMockReadableStream([signalResponse]);
|
|
456
|
+
const mockConnection = createMockConnection(mockReadable);
|
|
457
|
+
let capturedUrl = '';
|
|
458
|
+
|
|
459
|
+
mockWebSocketStream({
|
|
460
|
+
connection: mockConnection,
|
|
461
|
+
onUrl: (url) => {
|
|
462
|
+
capturedUrl = url;
|
|
463
|
+
},
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
await signalClient.join('wss://test.livekit.io', 'test-token', defaultOptions);
|
|
467
|
+
|
|
468
|
+
const joinRequest = await decodeJoinRequestFromUrl(capturedUrl);
|
|
469
|
+
expect(joinRequest.connectionSettings?.subscriberAllowPause).toBeUndefined();
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
it.each([true, false])(
|
|
473
|
+
'sets subscriberAllowPause=%s in the join request',
|
|
474
|
+
async (subscriberAllowPause) => {
|
|
475
|
+
const joinResponse = createJoinResponse();
|
|
476
|
+
const signalResponse = createSignalResponse('join', joinResponse);
|
|
477
|
+
const mockReadable = createMockReadableStream([signalResponse]);
|
|
478
|
+
const mockConnection = createMockConnection(mockReadable);
|
|
479
|
+
let capturedUrl = '';
|
|
480
|
+
|
|
481
|
+
mockWebSocketStream({
|
|
482
|
+
connection: mockConnection,
|
|
483
|
+
onUrl: (url) => {
|
|
484
|
+
capturedUrl = url;
|
|
485
|
+
},
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
await signalClient.join('wss://test.livekit.io', 'test-token', {
|
|
489
|
+
...defaultOptions,
|
|
490
|
+
subscriberAllowPause,
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
const joinRequest = await decodeJoinRequestFromUrl(capturedUrl);
|
|
494
|
+
expect(joinRequest.connectionSettings?.subscriberAllowPause).toBe(subscriberAllowPause);
|
|
495
|
+
},
|
|
496
|
+
);
|
|
497
|
+
|
|
498
|
+
it.each([
|
|
499
|
+
[undefined, null],
|
|
500
|
+
[true, '1'],
|
|
501
|
+
[false, '0'],
|
|
502
|
+
])(
|
|
503
|
+
'sets subscriber_allow_pause on the v0 path when subscriberAllowPause=%s',
|
|
504
|
+
async (subscriberAllowPause, expected) => {
|
|
505
|
+
const joinResponse = createJoinResponse();
|
|
506
|
+
const signalResponse = createSignalResponse('join', joinResponse);
|
|
507
|
+
const mockReadable = createMockReadableStream([signalResponse]);
|
|
508
|
+
const mockConnection = createMockConnection(mockReadable);
|
|
509
|
+
let capturedUrl = '';
|
|
510
|
+
|
|
511
|
+
mockWebSocketStream({
|
|
512
|
+
connection: mockConnection,
|
|
513
|
+
onUrl: (url) => {
|
|
514
|
+
capturedUrl = url;
|
|
515
|
+
},
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
await signalClient.join(
|
|
519
|
+
'wss://test.livekit.io',
|
|
520
|
+
'test-token',
|
|
521
|
+
{ ...defaultOptions, subscriberAllowPause },
|
|
522
|
+
undefined,
|
|
523
|
+
true,
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
expect(new URL(capturedUrl).searchParams.get('subscriber_allow_pause')).toBe(expected);
|
|
527
|
+
},
|
|
528
|
+
);
|
|
209
529
|
});
|
|
210
530
|
|
|
211
531
|
describe('Happy Path - Reconnect', () => {
|
|
@@ -236,7 +556,7 @@ describe('SignalClient.connect', () => {
|
|
|
236
556
|
expect(signalClient.currentState).toBe(SignalConnectionState.CONNECTED);
|
|
237
557
|
});
|
|
238
558
|
|
|
239
|
-
it('
|
|
559
|
+
it('drops stray messages during reconnect and waits for the reconnect response', async () => {
|
|
240
560
|
// First, initial connection
|
|
241
561
|
const joinResponse = createJoinResponse();
|
|
242
562
|
const joinSignalResponse = createSignalResponse('join', joinResponse);
|
|
@@ -247,19 +567,24 @@ describe('SignalClient.connect', () => {
|
|
|
247
567
|
|
|
248
568
|
await signalClient.join('wss://test.livekit.io', 'test-token', defaultOptions);
|
|
249
569
|
|
|
250
|
-
//
|
|
570
|
+
// Server sends a stray update first, then the actual reconnect response.
|
|
571
|
+
// The stray should be dropped with a warning; the reconnect response should resolve.
|
|
251
572
|
const updateSignalResponse = createSignalResponse('update', { participants: [] });
|
|
252
|
-
const
|
|
573
|
+
const reconnectResponse = new ReconnectResponse({ iceServers: [] });
|
|
574
|
+
const reconnectSignalResponse = createSignalResponse('reconnect', reconnectResponse);
|
|
575
|
+
const reconnectMockReadable = createMockReadableStream([
|
|
576
|
+
updateSignalResponse,
|
|
577
|
+
reconnectSignalResponse,
|
|
578
|
+
]);
|
|
253
579
|
const reconnectMockConnection = createMockConnection(reconnectMockReadable);
|
|
254
580
|
|
|
255
581
|
mockWebSocketStream({ connection: reconnectMockConnection });
|
|
256
582
|
|
|
257
583
|
const result = await signalClient.reconnect('wss://test.livekit.io', 'test-token', 'sid-123');
|
|
258
584
|
|
|
259
|
-
|
|
260
|
-
expect(result).toBeUndefined();
|
|
585
|
+
expect(result).toEqual(reconnectResponse);
|
|
261
586
|
expect(signalClient.currentState).toBe(SignalConnectionState.CONNECTED);
|
|
262
|
-
}
|
|
587
|
+
});
|
|
263
588
|
});
|
|
264
589
|
|
|
265
590
|
describe('Failure Case - Timeout', () => {
|
|
@@ -742,6 +1067,66 @@ describe('SignalClient.connect', () => {
|
|
|
742
1067
|
});
|
|
743
1068
|
});
|
|
744
1069
|
|
|
1070
|
+
describe('Failure Case - Validate Request Hangs', () => {
|
|
1071
|
+
// A socket that never opens on its own (a lossy network) and whose `opened` rejects once the
|
|
1072
|
+
// client closes it, like a real WebSocketStream aborted during the handshake.
|
|
1073
|
+
function mockHangingWebSocket() {
|
|
1074
|
+
vi.mocked(WebSocketStream).mockImplementationOnce(function () {
|
|
1075
|
+
let rejectOpened!: (e: unknown) => void;
|
|
1076
|
+
let resolveClosed!: (info: WebSocketCloseInfo) => void;
|
|
1077
|
+
return {
|
|
1078
|
+
url: 'wss://test.livekit.io',
|
|
1079
|
+
opened: new Promise((_, reject) => (rejectOpened = reject)),
|
|
1080
|
+
closed: new Promise((resolve) => (resolveClosed = resolve)),
|
|
1081
|
+
close: vi.fn(() => {
|
|
1082
|
+
rejectOpened(new Error('aborted during handshake'));
|
|
1083
|
+
resolveClosed({ closeCode: 1006, reason: '' });
|
|
1084
|
+
}),
|
|
1085
|
+
readyState: 0,
|
|
1086
|
+
} as any;
|
|
1087
|
+
});
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
it('does not let a timed-out attempt block the next one', async () => {
|
|
1091
|
+
// A validate request on a dead pooled connection only settles once its abort signal fires.
|
|
1092
|
+
// Without a deadline it held the connection lock, so the next attempt never started. A
|
|
1093
|
+
// timed-out attempt now skips validation entirely, since its caller has already been rejected.
|
|
1094
|
+
vi.useFakeTimers();
|
|
1095
|
+
try {
|
|
1096
|
+
const hangingFetch = (_url: unknown, init?: RequestInit) =>
|
|
1097
|
+
new Promise<Response>((_, reject) => {
|
|
1098
|
+
init?.signal?.addEventListener('abort', () => reject(init.signal!.reason));
|
|
1099
|
+
});
|
|
1100
|
+
vi.mocked(fetch).mockImplementationOnce(hangingFetch).mockImplementationOnce(hangingFetch);
|
|
1101
|
+
mockHangingWebSocket();
|
|
1102
|
+
mockHangingWebSocket();
|
|
1103
|
+
|
|
1104
|
+
// building the join request finishes on real I/O, so wait for each socket before advancing
|
|
1105
|
+
const first = expect(
|
|
1106
|
+
signalClient.join('wss://test.livekit.io', 'test-token', defaultOptions),
|
|
1107
|
+
).rejects.toMatchObject({ reason: ConnectionErrorReason.Timeout });
|
|
1108
|
+
await vi.waitFor(() => expect(WebSocketStream).toHaveBeenCalledTimes(1));
|
|
1109
|
+
await vi.advanceTimersByTimeAsync(defaultOptions.websocketTimeout);
|
|
1110
|
+
await first;
|
|
1111
|
+
|
|
1112
|
+
const second = expect(
|
|
1113
|
+
signalClient.join('wss://test.livekit.io', 'test-token', defaultOptions),
|
|
1114
|
+
).rejects.toMatchObject({ reason: ConnectionErrorReason.Timeout });
|
|
1115
|
+
// past the validate deadline, which is what releases the lock the first attempt holds
|
|
1116
|
+
await vi.advanceTimersByTimeAsync(10_000);
|
|
1117
|
+
await vi.waitFor(() => expect(WebSocketStream).toHaveBeenCalledTimes(2));
|
|
1118
|
+
await vi.advanceTimersByTimeAsync(defaultOptions.websocketTimeout);
|
|
1119
|
+
await second;
|
|
1120
|
+
|
|
1121
|
+
expect(fetch).not.toHaveBeenCalled();
|
|
1122
|
+
} finally {
|
|
1123
|
+
vi.useRealTimers();
|
|
1124
|
+
// drop the unused hanging fetches so they don't leak into later tests
|
|
1125
|
+
vi.mocked(fetch).mockReset();
|
|
1126
|
+
}
|
|
1127
|
+
});
|
|
1128
|
+
});
|
|
1129
|
+
|
|
745
1130
|
describe('Establishing over an existing session', () => {
|
|
746
1131
|
async function joinSuccessfully() {
|
|
747
1132
|
mockWebSocketStream({
|
|
@@ -1026,7 +1411,7 @@ describe('SignalClient.validateFirstMessage', () => {
|
|
|
1026
1411
|
}
|
|
1027
1412
|
});
|
|
1028
1413
|
|
|
1029
|
-
it('should
|
|
1414
|
+
it('should reject non-reconnect message during reconnecting state', async () => {
|
|
1030
1415
|
// First establish a connection
|
|
1031
1416
|
const joinResponse = createJoinResponse();
|
|
1032
1417
|
const joinSignalResponse = createSignalResponse('join', joinResponse);
|
|
@@ -1044,9 +1429,8 @@ describe('SignalClient.validateFirstMessage', () => {
|
|
|
1044
1429
|
const validateMethod = (signalClient as any).validateFirstMessage;
|
|
1045
1430
|
if (validateMethod) {
|
|
1046
1431
|
const result = validateMethod.call(signalClient, updateSignalResponse, true);
|
|
1047
|
-
expect(result.isValid).toBe(
|
|
1048
|
-
expect(result.
|
|
1049
|
-
expect(result.shouldProcessFirstMessage).toBe(true);
|
|
1432
|
+
expect(result.isValid).toBe(false);
|
|
1433
|
+
expect(result.error).toBeInstanceOf(ConnectionError);
|
|
1050
1434
|
}
|
|
1051
1435
|
});
|
|
1052
1436
|
|