livekit-client 2.22.0 → 2.22.2
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 +1 -1
- package/dist/livekit-client.e2ee.worker.js.map +1 -1
- package/dist/livekit-client.e2ee.worker.mjs +364 -40
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +1847 -179
- 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 +187 -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 +25 -1
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/api/SignalClientStateMachine.d.ts +85 -0
- package/dist/src/api/SignalClientStateMachine.d.ts.map +1 -0
- package/dist/src/api/WebSocketStream.d.ts.map +1 -1
- package/dist/src/api/utils.d.ts.map +1 -1
- package/dist/src/e2ee/E2eeManager.d.ts +7 -0
- package/dist/src/e2ee/E2eeManager.d.ts.map +1 -1
- package/dist/src/e2ee/constants.d.ts +5 -0
- package/dist/src/e2ee/constants.d.ts.map +1 -1
- package/dist/src/e2ee/types.d.ts +9 -2
- package/dist/src/e2ee/types.d.ts.map +1 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts +42 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/index.d.ts +3 -2
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/logger.d.ts +2 -1
- package/dist/src/logger.d.ts.map +1 -1
- package/dist/src/options.d.ts +22 -0
- package/dist/src/options.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +2 -1
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts +12 -0
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +7 -2
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +8 -1
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/data-stream/incoming/StreamReader.d.ts +17 -17
- package/dist/src/room/data-stream/incoming/StreamReader.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +1 -1
- package/dist/src/room/statsSummary.d.ts +13 -0
- package/dist/src/room/statsSummary.d.ts.map +1 -0
- package/dist/src/room/token-source/utils.d.ts.map +1 -1
- package/dist/src/room/track/LocalAudioTrack.d.ts.map +1 -1
- package/dist/src/room/track/Track.d.ts +10 -0
- package/dist/src/room/track/Track.d.ts.map +1 -1
- package/dist/src/utils/machineInspector.d.ts +54 -0
- package/dist/src/utils/machineInspector.d.ts.map +1 -0
- package/dist/ts4.2/api/SignalClient.d.ts +25 -1
- package/dist/ts4.2/api/SignalClientStateMachine.d.ts +85 -0
- package/dist/ts4.2/e2ee/E2eeManager.d.ts +7 -0
- package/dist/ts4.2/e2ee/constants.d.ts +5 -0
- package/dist/ts4.2/e2ee/types.d.ts +9 -2
- package/dist/ts4.2/e2ee/worker/FrameCryptor.d.ts +42 -1
- package/dist/ts4.2/index.d.ts +3 -2
- package/dist/ts4.2/logger.d.ts +2 -1
- package/dist/ts4.2/options.d.ts +22 -0
- package/dist/ts4.2/room/PCTransport.d.ts +2 -1
- package/dist/ts4.2/room/PCTransportManager.d.ts +12 -0
- package/dist/ts4.2/room/RTCEngine.d.ts +7 -2
- package/dist/ts4.2/room/Room.d.ts +8 -1
- package/dist/ts4.2/room/data-stream/incoming/StreamReader.d.ts +17 -17
- package/dist/ts4.2/room/events.d.ts +1 -1
- package/dist/ts4.2/room/statsSummary.d.ts +13 -0
- package/dist/ts4.2/room/track/Track.d.ts +10 -0
- package/dist/ts4.2/utils/machineInspector.d.ts +54 -0
- package/package.json +7 -1
- package/src/api/SignalClient.test.ts +320 -8
- package/src/api/SignalClient.ts +261 -82
- package/src/api/SignalClientStateMachine.test.ts +472 -0
- package/src/api/SignalClientStateMachine.ts +180 -0
- package/src/api/WebSocketStream.ts +19 -3
- package/src/api/utils.test.ts +20 -1
- package/src/api/utils.ts +5 -0
- package/src/e2ee/E2eeManager.ts +38 -14
- package/src/e2ee/constants.ts +6 -0
- package/src/e2ee/subscriberBlackScreen.test.ts +544 -0
- package/src/e2ee/types.ts +9 -2
- package/src/e2ee/worker/FrameCryptor.race.test.ts +9 -26
- package/src/e2ee/worker/FrameCryptor.test.ts +0 -1
- package/src/e2ee/worker/FrameCryptor.ts +185 -52
- package/src/e2ee/worker/e2ee.worker.ts +38 -6
- package/src/index.ts +5 -0
- package/src/logger.ts +1 -0
- package/src/options.ts +24 -0
- package/src/room/PCTransport.ts +2 -1
- package/src/room/PCTransportManager.test.ts +35 -0
- package/src/room/PCTransportManager.ts +12 -4
- package/src/room/RTCEngine.ts +16 -7
- package/src/room/Room.ts +70 -5
- package/src/room/data-stream/incoming/IncomingDataStreamManager.test.ts +171 -0
- package/src/room/data-stream/incoming/IncomingDataStreamManager.ts +17 -18
- package/src/room/data-stream/incoming/StreamReader.ts +20 -50
- package/src/room/events.ts +1 -1
- package/src/room/statsSummary.ts +187 -0
- package/src/room/token-source/test-tokens.ts +20 -0
- package/src/room/token-source/utils.test.ts +27 -0
- package/src/room/token-source/utils.ts +12 -5
- package/src/room/track/LocalAudioTrack.ts +9 -3
- package/src/room/track/Track.ts +27 -0
- package/src/room/utils.test.ts +24 -1
- package/src/room/utils.ts +1 -1
- package/src/utils/machineInspector.ts +90 -0
package/src/api/utils.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { createRtcUrl, createValidateUrl } from './utils';
|
|
2
|
+
import { createRtcUrl, createValidateUrl, getAbortReasonAsString } from './utils';
|
|
3
3
|
|
|
4
4
|
describe('createRtcUrl', () => {
|
|
5
5
|
it('should create a basic RTC URL', () => {
|
|
@@ -125,3 +125,22 @@ describe('createValidateUrl', () => {
|
|
|
125
125
|
expect(parsedResult.pathname).toBe('/sub/path/rtc/validate');
|
|
126
126
|
});
|
|
127
127
|
});
|
|
128
|
+
|
|
129
|
+
describe('getAbortReasonAsString', () => {
|
|
130
|
+
it('uses an error message, which is how the connect timeout describes itself', () => {
|
|
131
|
+
// the timeout hands the abort handler an Error, not a signal
|
|
132
|
+
expect(
|
|
133
|
+
getAbortReasonAsString(new Error('room connection has timed out (signal)'), 'fallback'),
|
|
134
|
+
).toBe('room connection has timed out (signal)');
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it("reads an abort signal's reason", () => {
|
|
138
|
+
const controller = new AbortController();
|
|
139
|
+
controller.abort('user navigated away');
|
|
140
|
+
expect(getAbortReasonAsString(controller.signal, 'fallback')).toBe('user navigated away');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('falls back when there is nothing to describe', () => {
|
|
144
|
+
expect(getAbortReasonAsString(undefined, 'fallback')).toBe('fallback');
|
|
145
|
+
});
|
|
146
|
+
});
|
package/src/api/utils.ts
CHANGED
|
@@ -45,6 +45,11 @@ export function getAbortReasonAsString(
|
|
|
45
45
|
signal: AbortSignal | Error | unknown,
|
|
46
46
|
defaultMessage = 'Unknown reason',
|
|
47
47
|
) {
|
|
48
|
+
// the connect timeout hands this an Error rather than a signal, and its message is the only
|
|
49
|
+
// description of what went wrong — without this a timeout reports itself as a generic abort
|
|
50
|
+
if (signal instanceof Error) {
|
|
51
|
+
return signal.message;
|
|
52
|
+
}
|
|
48
53
|
if (!(signal instanceof AbortSignal)) {
|
|
49
54
|
return defaultMessage;
|
|
50
55
|
}
|
package/src/e2ee/E2eeManager.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { EngineEvent, ParticipantEvent, RoomEvent } from '../room/events';
|
|
|
12
12
|
import type RemoteTrack from '../room/track/RemoteTrack';
|
|
13
13
|
import RemoteVideoTrack from '../room/track/RemoteVideoTrack';
|
|
14
14
|
import type { Track } from '../room/track/Track';
|
|
15
|
+
import type { TrackPublication } from '../room/track/TrackPublication';
|
|
15
16
|
import type { TrackPublishOptions, VideoCodec } from '../room/track/options';
|
|
16
17
|
import { mimeTypeToVideoCodecString } from '../room/track/utils';
|
|
17
18
|
import {
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
} from '../room/utils';
|
|
24
25
|
import type { NonSharedUint8Array } from '../type-polyfills/non-shared-typed-arrays';
|
|
25
26
|
import type { BaseKeyProvider } from './KeyProvider';
|
|
26
|
-
import { E2EE_FLAG } from './constants';
|
|
27
|
+
import { E2EE_FLAG, E2EE_TRACK_ID } from './constants';
|
|
27
28
|
import { type E2EEManagerCallbacks, EncryptionEvent, KeyProviderEvent } from './events';
|
|
28
29
|
import type {
|
|
29
30
|
DecryptDataRequestMessage,
|
|
@@ -279,20 +280,14 @@ export class E2EEManager
|
|
|
279
280
|
|
|
280
281
|
private setupEventListeners(room: Room, keyProvider: BaseKeyProvider) {
|
|
281
282
|
room.on(RoomEvent.TrackPublished, (pub, participant) =>
|
|
282
|
-
this.
|
|
283
|
-
pub.trackInfo!.encryption !== Encryption_Type.NONE,
|
|
284
|
-
participant.identity,
|
|
285
|
-
),
|
|
283
|
+
this.setParticipantCryptorEnabledForPublication(pub, participant.identity),
|
|
286
284
|
);
|
|
287
285
|
room
|
|
288
286
|
.on(RoomEvent.ConnectionStateChanged, (state) => {
|
|
289
287
|
if (state === ConnectionState.Connected) {
|
|
290
288
|
room.remoteParticipants.forEach((participant) => {
|
|
291
289
|
participant.trackPublications.forEach((pub) => {
|
|
292
|
-
this.
|
|
293
|
-
pub.trackInfo!.encryption !== Encryption_Type.NONE,
|
|
294
|
-
participant.identity,
|
|
295
|
-
);
|
|
290
|
+
this.setParticipantCryptorEnabledForPublication(pub, participant.identity);
|
|
296
291
|
});
|
|
297
292
|
});
|
|
298
293
|
}
|
|
@@ -482,6 +477,29 @@ export class E2EEManager
|
|
|
482
477
|
this.worker.postMessage(msg);
|
|
483
478
|
}
|
|
484
479
|
|
|
480
|
+
/**
|
|
481
|
+
* Derive the participant's encryption state from one of its publications.
|
|
482
|
+
* Publications without trackInfo are skipped rather than thrown on: throwing
|
|
483
|
+
* inside the forEach above would leave every remaining participant without an
|
|
484
|
+
* encryption state, and a cryptor with unknown state can no longer decrypt.
|
|
485
|
+
*/
|
|
486
|
+
private setParticipantCryptorEnabledForPublication(
|
|
487
|
+
pub: TrackPublication,
|
|
488
|
+
participantIdentity: string,
|
|
489
|
+
) {
|
|
490
|
+
if (!pub.trackInfo) {
|
|
491
|
+
log.warn('skipping e2ee enabled update for publication without trackInfo', {
|
|
492
|
+
participant: participantIdentity,
|
|
493
|
+
trackSid: pub.trackSid,
|
|
494
|
+
});
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
this.setParticipantCryptorEnabled(
|
|
498
|
+
pub.trackInfo.encryption !== Encryption_Type.NONE,
|
|
499
|
+
participantIdentity,
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
|
|
485
503
|
private setupE2EEReceiver(track: RemoteTrack, remoteId: string, trackInfo?: TrackInfo) {
|
|
486
504
|
if (!track.receiver) {
|
|
487
505
|
return;
|
|
@@ -541,21 +559,27 @@ export class E2EEManager
|
|
|
541
559
|
codec,
|
|
542
560
|
hasPacketTrailer,
|
|
543
561
|
};
|
|
544
|
-
// @ts-ignore
|
|
545
562
|
receiver.transform = new RTCRtpScriptTransform(this.worker, options);
|
|
546
563
|
} else {
|
|
547
|
-
if (E2EE_FLAG in receiver &&
|
|
548
|
-
//
|
|
564
|
+
if (E2EE_FLAG in receiver && E2EE_TRACK_ID in receiver) {
|
|
565
|
+
// The transceiver is being reused for a new track. We cannot set up a new
|
|
566
|
+
// pipeline from here: this receiver's encoded streams were transferred to
|
|
567
|
+
// the worker on first setup and a transferred stream can't be transferred
|
|
568
|
+
// again, while createEncodedStreams() may only be called once per receiver.
|
|
569
|
+
// So hand the worker the new track/participant and let it re-point (and if
|
|
570
|
+
// necessary rebuild) the cryptor that still owns those streams.
|
|
549
571
|
const msg: UpdateCodecMessage = {
|
|
550
572
|
kind: 'updateCodec',
|
|
551
573
|
data: {
|
|
552
574
|
trackId,
|
|
575
|
+
previousTrackId: receiver[E2EE_TRACK_ID] as string,
|
|
553
576
|
codec,
|
|
554
577
|
participantIdentity,
|
|
555
578
|
hasPacketTrailer,
|
|
556
579
|
},
|
|
557
580
|
};
|
|
558
581
|
this.worker.postMessage(msg);
|
|
582
|
+
receiver[E2EE_TRACK_ID] = trackId;
|
|
559
583
|
return;
|
|
560
584
|
}
|
|
561
585
|
// @ts-ignore
|
|
@@ -582,7 +606,6 @@ export class E2EEManager
|
|
|
582
606
|
trackId: trackId,
|
|
583
607
|
codec,
|
|
584
608
|
participantIdentity: participantIdentity,
|
|
585
|
-
isReuse: E2EE_FLAG in receiver,
|
|
586
609
|
hasPacketTrailer,
|
|
587
610
|
},
|
|
588
611
|
};
|
|
@@ -591,6 +614,8 @@ export class E2EEManager
|
|
|
591
614
|
|
|
592
615
|
// @ts-ignore
|
|
593
616
|
receiver[E2EE_FLAG] = true;
|
|
617
|
+
// @ts-ignore
|
|
618
|
+
receiver[E2EE_TRACK_ID] = trackId;
|
|
594
619
|
}
|
|
595
620
|
|
|
596
621
|
/**
|
|
@@ -636,7 +661,6 @@ export class E2EEManager
|
|
|
636
661
|
codec,
|
|
637
662
|
trackId,
|
|
638
663
|
participantIdentity: this.room.localParticipant.identity,
|
|
639
|
-
isReuse: false,
|
|
640
664
|
hasPacketTrailer: hasFrameMetadataPublishOptions(frameMetadata),
|
|
641
665
|
packetTrailer: frameMetadata,
|
|
642
666
|
},
|
package/src/e2ee/constants.ts
CHANGED
|
@@ -29,6 +29,12 @@ export const IV_LENGTH = 12;
|
|
|
29
29
|
// flag set to indicate that e2ee has been setup for sender/receiver;
|
|
30
30
|
export const E2EE_FLAG = 'lk_e2ee';
|
|
31
31
|
|
|
32
|
+
/**
|
|
33
|
+
* trackId a receiver's/sender's encoded stream pipeline was last set up for.
|
|
34
|
+
* Needed to recover the right cryptor when a transceiver gets reused.
|
|
35
|
+
*/
|
|
36
|
+
export const E2EE_TRACK_ID = 'lk_e2ee_track_id';
|
|
37
|
+
|
|
32
38
|
export const SALT = 'LKFrameEncryptionKey';
|
|
33
39
|
|
|
34
40
|
export const KEY_PROVIDER_DEFAULTS: KeyProviderOptions = {
|