livekit-client 2.18.0 → 2.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +8 -7
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +7832 -5799
- package/dist/livekit-client.esm.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 +12 -4
- package/dist/src/api/SignalClient.d.ts.map +1 -1
- package/dist/src/e2ee/constants.d.ts.map +1 -1
- package/dist/src/e2ee/types.d.ts +6 -0
- package/dist/src/e2ee/types.d.ts.map +1 -1
- package/dist/src/e2ee/utils.d.ts +2 -1
- package/dist/src/e2ee/utils.d.ts.map +1 -1
- package/dist/src/e2ee/worker/DataCryptor.d.ts.map +1 -1
- package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
- package/dist/src/index.d.ts +5 -4
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/room/PCTransport.d.ts +5 -0
- package/dist/src/room/PCTransport.d.ts.map +1 -1
- package/dist/src/room/PCTransportManager.d.ts +1 -1
- package/dist/src/room/PCTransportManager.d.ts.map +1 -1
- package/dist/src/room/RTCEngine.d.ts +24 -8
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +13 -3
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts.map +1 -1
- package/dist/src/room/data-track/LocalDataTrack.d.ts +28 -5
- package/dist/src/room/data-track/LocalDataTrack.d.ts.map +1 -1
- package/dist/src/room/data-track/RemoteDataTrack.d.ts +5 -5
- package/dist/src/room/data-track/RemoteDataTrack.d.ts.map +1 -1
- package/dist/src/room/data-track/depacketizer.d.ts +4 -4
- package/dist/src/room/data-track/depacketizer.d.ts.map +1 -1
- package/dist/src/room/data-track/frame.d.ts +14 -0
- package/dist/src/room/data-track/frame.d.ts.map +1 -1
- package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts +19 -11
- package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts.map +1 -1
- package/dist/src/room/data-track/incoming/pipeline.d.ts +6 -5
- package/dist/src/room/data-track/incoming/pipeline.d.ts.map +1 -1
- package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +57 -23
- package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts.map +1 -1
- package/dist/src/room/data-track/outgoing/errors.d.ts +16 -6
- package/dist/src/room/data-track/outgoing/errors.d.ts.map +1 -1
- package/dist/src/room/data-track/outgoing/pipeline.d.ts +7 -6
- package/dist/src/room/data-track/outgoing/pipeline.d.ts.map +1 -1
- package/dist/src/room/data-track/outgoing/types.d.ts +14 -4
- package/dist/src/room/data-track/outgoing/types.d.ts.map +1 -1
- package/dist/src/room/data-track/packet/extensions.d.ts.map +1 -1
- package/dist/src/room/data-track/packetizer.d.ts +4 -4
- package/dist/src/room/data-track/packetizer.d.ts.map +1 -1
- package/dist/src/room/data-track/track-interfaces.d.ts +1 -1
- package/dist/src/room/data-track/track-interfaces.d.ts.map +1 -1
- package/dist/src/room/data-track/types.d.ts +6 -1
- package/dist/src/room/data-track/types.d.ts.map +1 -1
- package/dist/src/room/events.d.ts +24 -3
- package/dist/src/room/events.d.ts.map +1 -1
- package/dist/src/room/participant/LocalParticipant.d.ts +11 -1
- package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
- package/dist/src/room/participant/RemoteParticipant.d.ts +13 -0
- package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
- package/dist/src/room/utils.d.ts +1 -0
- package/dist/src/room/utils.d.ts.map +1 -1
- package/dist/src/utils/deferrable-map.d.ts +32 -0
- package/dist/src/utils/deferrable-map.d.ts.map +1 -0
- package/dist/ts4.2/api/SignalClient.d.ts +12 -4
- package/dist/ts4.2/e2ee/types.d.ts +6 -0
- package/dist/ts4.2/e2ee/utils.d.ts +2 -1
- package/dist/ts4.2/index.d.ts +5 -4
- package/dist/ts4.2/room/PCTransport.d.ts +5 -0
- package/dist/ts4.2/room/PCTransportManager.d.ts +1 -1
- package/dist/ts4.2/room/RTCEngine.d.ts +24 -8
- package/dist/ts4.2/room/Room.d.ts +13 -3
- package/dist/ts4.2/room/data-track/LocalDataTrack.d.ts +27 -4
- package/dist/ts4.2/room/data-track/RemoteDataTrack.d.ts +4 -4
- package/dist/ts4.2/room/data-track/depacketizer.d.ts +4 -4
- package/dist/ts4.2/room/data-track/frame.d.ts +14 -0
- package/dist/ts4.2/room/data-track/incoming/IncomingDataTrackManager.d.ts +21 -10
- package/dist/ts4.2/room/data-track/incoming/pipeline.d.ts +6 -5
- package/dist/ts4.2/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +57 -23
- package/dist/ts4.2/room/data-track/outgoing/errors.d.ts +16 -6
- package/dist/ts4.2/room/data-track/outgoing/pipeline.d.ts +7 -6
- package/dist/ts4.2/room/data-track/outgoing/types.d.ts +14 -4
- package/dist/ts4.2/room/data-track/packetizer.d.ts +4 -4
- package/dist/ts4.2/room/data-track/track-interfaces.d.ts +1 -1
- package/dist/ts4.2/room/data-track/types.d.ts +6 -1
- package/dist/ts4.2/room/events.d.ts +24 -3
- package/dist/ts4.2/room/participant/LocalParticipant.d.ts +11 -1
- package/dist/ts4.2/room/participant/RemoteParticipant.d.ts +13 -0
- package/dist/ts4.2/room/utils.d.ts +1 -0
- package/dist/ts4.2/utils/deferrable-map.d.ts +32 -0
- package/package.json +1 -1
- package/src/api/SignalClient.test.ts +9 -4
- package/src/api/SignalClient.ts +116 -9
- package/src/e2ee/constants.ts +1 -0
- package/src/e2ee/types.ts +6 -0
- package/src/e2ee/utils.ts +4 -3
- package/src/e2ee/worker/DataCryptor.ts +1 -4
- package/src/e2ee/worker/FrameCryptor.ts +1 -4
- package/src/e2ee/worker/ParticipantKeyHandler.ts +1 -1
- package/src/index.ts +6 -4
- package/src/room/PCTransport.ts +41 -1
- package/src/room/PCTransportManager.ts +1 -1
- package/src/room/RTCEngine.ts +266 -111
- package/src/room/Room.ts +149 -12
- package/src/room/data-stream/outgoing/OutgoingDataStreamManager.ts +7 -7
- package/src/room/data-track/LocalDataTrack.ts +83 -10
- package/src/room/data-track/RemoteDataTrack.ts +7 -9
- package/src/room/data-track/depacketizer.ts +21 -12
- package/src/room/data-track/frame.ts +28 -2
- package/src/room/data-track/incoming/IncomingDataTrackManager.test.ts +58 -73
- package/src/room/data-track/incoming/IncomingDataTrackManager.ts +132 -80
- package/src/room/data-track/incoming/pipeline.ts +29 -24
- package/src/room/data-track/outgoing/OutgoingDataTrackManager.test.ts +225 -32
- package/src/room/data-track/outgoing/OutgoingDataTrackManager.ts +150 -75
- package/src/room/data-track/outgoing/errors.ts +36 -7
- package/src/room/data-track/outgoing/pipeline.ts +23 -17
- package/src/room/data-track/outgoing/types.ts +12 -3
- package/src/room/data-track/packet/extensions.ts +17 -22
- package/src/room/data-track/packet/index.test.ts +22 -33
- package/src/room/data-track/packetizer.test.ts +2 -2
- package/src/room/data-track/packetizer.ts +4 -4
- package/src/room/data-track/track-interfaces.ts +1 -1
- package/src/room/data-track/types.ts +21 -1
- package/src/room/events.ts +26 -1
- package/src/room/participant/LocalParticipant.ts +57 -6
- package/src/room/participant/RemoteParticipant.ts +25 -0
- package/src/room/utils.ts +4 -0
- package/src/utils/deferrable-map.ts +109 -0
- package/dist/src/room/data-track/e2ee.d.ts +0 -12
- package/dist/src/room/data-track/e2ee.d.ts.map +0 -1
- package/dist/ts4.2/room/data-track/e2ee.d.ts +0 -12
- package/src/room/data-track/e2ee.ts +0 -15
|
@@ -72,7 +72,7 @@ describe('DataTrackPacket', () => {
|
|
|
72
72
|
|
|
73
73
|
const packet = new DataTrackPacket(header, payloadBytes);
|
|
74
74
|
|
|
75
|
-
expect(packet.toBinaryLengthBytes()).toStrictEqual(
|
|
75
|
+
expect(packet.toBinaryLengthBytes()).toStrictEqual(74);
|
|
76
76
|
expect(packet.toBinary()).toStrictEqual(
|
|
77
77
|
new Uint8Array([
|
|
78
78
|
0xc, // Version 0, final, extension
|
|
@@ -88,13 +88,11 @@ describe('DataTrackPacket', () => {
|
|
|
88
88
|
17,
|
|
89
89
|
136,
|
|
90
90
|
0, // Rtp oriented extension words (big endian)
|
|
91
|
-
|
|
91
|
+
6,
|
|
92
92
|
|
|
93
93
|
// E2ee extension
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
0, // Length 12 (big endian)
|
|
97
|
-
12,
|
|
94
|
+
1, // ID 1
|
|
95
|
+
13, // Length 13
|
|
98
96
|
0xfa, // Key index
|
|
99
97
|
0x3c, // Iv array
|
|
100
98
|
0x3c,
|
|
@@ -110,10 +108,8 @@ describe('DataTrackPacket', () => {
|
|
|
110
108
|
0x3c,
|
|
111
109
|
|
|
112
110
|
// User timestamp extension
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
0, // Length 7 (big endian)
|
|
116
|
-
7,
|
|
111
|
+
2, // ID 2
|
|
112
|
+
8, // Length 8
|
|
117
113
|
68, // Timestamp value (big endian)
|
|
118
114
|
17,
|
|
119
115
|
34,
|
|
@@ -178,7 +174,7 @@ describe('DataTrackPacket', () => {
|
|
|
178
174
|
|
|
179
175
|
const packet = new DataTrackPacket(header, payloadBytes);
|
|
180
176
|
|
|
181
|
-
expect(packet.toBinaryLengthBytes()).toStrictEqual(
|
|
177
|
+
expect(packet.toBinaryLengthBytes()).toStrictEqual(62);
|
|
182
178
|
expect(packet.toBinary()).toStrictEqual(
|
|
183
179
|
new Uint8Array([
|
|
184
180
|
0x14, // Version 0, start, extension
|
|
@@ -194,13 +190,11 @@ describe('DataTrackPacket', () => {
|
|
|
194
190
|
0,
|
|
195
191
|
104,
|
|
196
192
|
0, // RTP oriented extension words (big endian)
|
|
197
|
-
|
|
193
|
+
3,
|
|
198
194
|
|
|
199
195
|
// E2ee extension
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
0, // Length 12 (big endian)
|
|
203
|
-
12,
|
|
196
|
+
1, // ID 1
|
|
197
|
+
13, // Length 13
|
|
204
198
|
0xfa, // Key index
|
|
205
199
|
0x3c, // Iv array
|
|
206
200
|
0x3c,
|
|
@@ -216,8 +210,6 @@ describe('DataTrackPacket', () => {
|
|
|
216
210
|
0x3c,
|
|
217
211
|
|
|
218
212
|
0, // Extension padding
|
|
219
|
-
0,
|
|
220
|
-
0,
|
|
221
213
|
|
|
222
214
|
0xfa, // Payload
|
|
223
215
|
0xfa,
|
|
@@ -431,13 +423,11 @@ describe('DataTrackPacket', () => {
|
|
|
431
423
|
...VALID_PACKET_BYTES,
|
|
432
424
|
|
|
433
425
|
0, // RTP oriented extension words (big endian)
|
|
434
|
-
|
|
426
|
+
3,
|
|
435
427
|
|
|
436
428
|
// E2ee extension
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
0, // Length 12 (big endian)
|
|
440
|
-
12,
|
|
429
|
+
1, // ID 1
|
|
430
|
+
12, // Length 12
|
|
441
431
|
0xfa, // Key index
|
|
442
432
|
0x3c, // Iv array
|
|
443
433
|
0x3c,
|
|
@@ -453,8 +443,6 @@ describe('DataTrackPacket', () => {
|
|
|
453
443
|
0x3c,
|
|
454
444
|
|
|
455
445
|
0, // Padding
|
|
456
|
-
0,
|
|
457
|
-
0,
|
|
458
446
|
]);
|
|
459
447
|
packetBytes[0] |= 1 << EXT_FLAG_SHIFT; // Extension flag
|
|
460
448
|
|
|
@@ -476,10 +464,8 @@ describe('DataTrackPacket', () => {
|
|
|
476
464
|
2,
|
|
477
465
|
|
|
478
466
|
// User timestamp extension
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
0, // Length 7 (big endian)
|
|
482
|
-
7,
|
|
467
|
+
2, // ID 2
|
|
468
|
+
7, // Length 7
|
|
483
469
|
0x44, // Timestamp (big endian)
|
|
484
470
|
0x11,
|
|
485
471
|
0x22,
|
|
@@ -488,6 +474,9 @@ describe('DataTrackPacket', () => {
|
|
|
488
474
|
0x11,
|
|
489
475
|
0x88,
|
|
490
476
|
0x11,
|
|
477
|
+
|
|
478
|
+
0, // Padding
|
|
479
|
+
0,
|
|
491
480
|
]);
|
|
492
481
|
packetBytes[0] |= 1 << EXT_FLAG_SHIFT; // Extension flag
|
|
493
482
|
|
|
@@ -508,19 +497,19 @@ describe('DataTrackPacket', () => {
|
|
|
508
497
|
2,
|
|
509
498
|
|
|
510
499
|
// Unknown / potential future extension
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
0, // Length 12 (big endian)
|
|
514
|
-
6,
|
|
500
|
+
8, // ID 8
|
|
501
|
+
6, // Length 6
|
|
515
502
|
0x1, // Payload
|
|
516
503
|
0x2,
|
|
517
504
|
0x3,
|
|
518
505
|
0x4,
|
|
519
506
|
0x5,
|
|
520
507
|
0x6,
|
|
508
|
+
0x0,
|
|
521
509
|
|
|
522
510
|
0x0, // Padding
|
|
523
511
|
0x0,
|
|
512
|
+
0x0,
|
|
524
513
|
]);
|
|
525
514
|
packetBytes[0] |= 1 << EXT_FLAG_SHIFT; // Extension flag
|
|
526
515
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
-
import {
|
|
3
|
+
import { DataTrackFrameInternal } from './frame';
|
|
4
4
|
import { DataTrackHandle } from './handle';
|
|
5
5
|
import { FrameMarker } from './packet';
|
|
6
6
|
import { DataTrackExtensions } from './packet/extensions';
|
|
@@ -90,7 +90,7 @@ describe('DataTrackPacketizer', () => {
|
|
|
90
90
|
])('should test packetizer edge cases', (payloadSizeBytes, mtuSizeBytes, label) => {
|
|
91
91
|
const packetizer = new DataTrackPacketizer(DataTrackHandle.fromNumber(1), mtuSizeBytes);
|
|
92
92
|
|
|
93
|
-
const frame:
|
|
93
|
+
const frame: DataTrackFrameInternal = {
|
|
94
94
|
payload: new Uint8Array(payloadSizeBytes).fill(0xab),
|
|
95
95
|
extensions: new DataTrackExtensions(),
|
|
96
96
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Throws } from '@livekit/throws-transformer/throws';
|
|
2
2
|
import { LivekitReasonedError } from '../errors';
|
|
3
|
-
import { type
|
|
3
|
+
import { type DataTrackFrameInternal } from './frame';
|
|
4
4
|
import { DataTrackHandle } from './handle';
|
|
5
5
|
import { DataTrackPacket, DataTrackPacketHeader, FrameMarker } from './packet';
|
|
6
6
|
import { DataTrackClock, DataTrackTimestamp, WrapAroundUnsignedInt } from './utils';
|
|
@@ -38,7 +38,7 @@ export enum DataTrackPacketizerReason {
|
|
|
38
38
|
MtuTooShort = 0,
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
/** A packetizer takes a {@link
|
|
41
|
+
/** A packetizer takes a {@link DataTrackFrameInternal} as input and generates a series
|
|
42
42
|
* of {@link DataTrackPacket}s for transmission to other clients over webrtc. */
|
|
43
43
|
export default class DataTrackPacketizer {
|
|
44
44
|
private handle: DataTrackHandle;
|
|
@@ -70,13 +70,13 @@ export default class DataTrackPacketizer {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
/** Generates a series of packets for the specified {@link
|
|
73
|
+
/** Generates a series of packets for the specified {@link DataTrackFrameInternal}.
|
|
74
74
|
*
|
|
75
75
|
* NOTE: The return value of this function is a generator, so it can be lazily ran if desired,
|
|
76
76
|
* or converted to an array with {@link Array.from}.
|
|
77
77
|
*/
|
|
78
78
|
*packetize(
|
|
79
|
-
frame:
|
|
79
|
+
frame: DataTrackFrameInternal,
|
|
80
80
|
options?: PacketizeOptions,
|
|
81
81
|
): Throws<Generator<DataTrackPacket>, DataTrackPacketizerError> {
|
|
82
82
|
const frameNumber = this.frameNumber.getThenIncrement();
|
|
@@ -45,7 +45,7 @@ export const DataTrackSymbol: symbol = Symbol.for('lk.data-track');
|
|
|
45
45
|
export interface IDataTrack extends ITrack {
|
|
46
46
|
readonly typeSymbol: typeof DataTrackSymbol;
|
|
47
47
|
|
|
48
|
-
readonly info
|
|
48
|
+
readonly info?: DataTrackInfo;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
export function isDataTrack(subject: unknown): subject is IDataTrack {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Encryption_Type, DataTrackInfo as ProtocolDataTrackInfo } from '@livekit/protocol';
|
|
1
2
|
import { type DataTrackHandle } from './handle';
|
|
2
3
|
|
|
3
4
|
export type DataTrackSid = string;
|
|
@@ -6,6 +7,25 @@ export type DataTrackSid = string;
|
|
|
6
7
|
export type DataTrackInfo = {
|
|
7
8
|
sid: DataTrackSid;
|
|
8
9
|
pubHandle: DataTrackHandle;
|
|
9
|
-
name:
|
|
10
|
+
name: string;
|
|
10
11
|
usesE2ee: boolean;
|
|
11
12
|
};
|
|
13
|
+
|
|
14
|
+
export const DataTrackInfo = {
|
|
15
|
+
from(protocolInfo: ProtocolDataTrackInfo): DataTrackInfo {
|
|
16
|
+
return {
|
|
17
|
+
sid: protocolInfo.sid,
|
|
18
|
+
pubHandle: protocolInfo.pubHandle,
|
|
19
|
+
name: protocolInfo.name,
|
|
20
|
+
usesE2ee: protocolInfo.encryption !== Encryption_Type.NONE,
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
toProtobuf(info: DataTrackInfo): ProtocolDataTrackInfo {
|
|
24
|
+
return new ProtocolDataTrackInfo({
|
|
25
|
+
sid: info.sid,
|
|
26
|
+
pubHandle: info.pubHandle,
|
|
27
|
+
name: info.name,
|
|
28
|
+
encryption: info.usesE2ee ? Encryption_Type.GCM : Encryption_Type.NONE,
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
};
|
package/src/room/events.ts
CHANGED
|
@@ -332,7 +332,7 @@ export enum RoomEvent {
|
|
|
332
332
|
EncryptionError = 'encryptionError',
|
|
333
333
|
/**
|
|
334
334
|
* Emits whenever the current buffer status of a data channel changes
|
|
335
|
-
* args: (isLow: boolean, kind: [[
|
|
335
|
+
* args: (isLow: boolean, kind: [[DataChannelKind]])
|
|
336
336
|
*/
|
|
337
337
|
DCBufferStatusChanged = 'dcBufferStatusChanged',
|
|
338
338
|
|
|
@@ -352,6 +352,26 @@ export enum RoomEvent {
|
|
|
352
352
|
* fired when the client receives connection metrics from other participants
|
|
353
353
|
*/
|
|
354
354
|
MetricsReceived = 'metricsReceived',
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Emits when a new data track has been published by a downstream participant.
|
|
358
|
+
*/
|
|
359
|
+
DataTrackPublished = 'dataTrackPublished',
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Emits when a new data track has been unpublished by a downstream participant.
|
|
363
|
+
*/
|
|
364
|
+
DataTrackUnpublished = 'dataTrackUnpublished',
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Emits when a new data track has been published locally.
|
|
368
|
+
*/
|
|
369
|
+
LocalDataTrackPublished = 'localDataTrackPublished',
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Emits when a new data track has been unpublished locally.
|
|
373
|
+
*/
|
|
374
|
+
LocalDataTrackUnpublished = 'localDataTrackUnpublished',
|
|
355
375
|
}
|
|
356
376
|
|
|
357
377
|
export enum ParticipantEvent {
|
|
@@ -606,6 +626,11 @@ export enum EngineEvent {
|
|
|
606
626
|
SignalRequestResponse = 'signalRequestResponse',
|
|
607
627
|
SignalConnected = 'signalConnected',
|
|
608
628
|
RoomMoved = 'roomMoved',
|
|
629
|
+
PublishDataTrackResponse = 'publishDataTrackResponse',
|
|
630
|
+
UnPublishDataTrackResponse = 'unPublishDataTrackResponse',
|
|
631
|
+
DataTrackSubscriberHandles = 'dataTrackSubscriberHandles',
|
|
632
|
+
DataTrackPacketReceived = 'dataTrackPacketReceived',
|
|
633
|
+
Joined = 'joined',
|
|
609
634
|
}
|
|
610
635
|
|
|
611
636
|
export enum TrackEvent {
|
|
@@ -27,8 +27,13 @@ import type { InternalRoomOptions } from '../../options';
|
|
|
27
27
|
import TypedPromise from '../../utils/TypedPromise';
|
|
28
28
|
import { PCTransportState } from '../PCTransportManager';
|
|
29
29
|
import type RTCEngine from '../RTCEngine';
|
|
30
|
+
import { DataChannelKind } from '../RTCEngine';
|
|
30
31
|
import type OutgoingDataStreamManager from '../data-stream/outgoing/OutgoingDataStreamManager';
|
|
31
32
|
import type { TextStreamWriter } from '../data-stream/outgoing/StreamWriter';
|
|
33
|
+
import LocalDataTrack from '../data-track/LocalDataTrack';
|
|
34
|
+
import type OutgoingDataTrackManager from '../data-track/outgoing/OutgoingDataTrackManager';
|
|
35
|
+
import { DataTrackPublishError } from '../data-track/outgoing/errors';
|
|
36
|
+
import type { DataTrackOptions } from '../data-track/outgoing/types';
|
|
32
37
|
import { defaultVideoCodec } from '../defaults';
|
|
33
38
|
import {
|
|
34
39
|
DeviceUnsupportedError,
|
|
@@ -150,6 +155,8 @@ export default class LocalParticipant extends Participant {
|
|
|
150
155
|
|
|
151
156
|
private roomOutgoingDataStreamManager: OutgoingDataStreamManager;
|
|
152
157
|
|
|
158
|
+
private roomOutgoingDataTrackManager: OutgoingDataTrackManager;
|
|
159
|
+
|
|
153
160
|
private pendingSignalRequests: Map<
|
|
154
161
|
number,
|
|
155
162
|
{
|
|
@@ -179,6 +186,7 @@ export default class LocalParticipant extends Participant {
|
|
|
179
186
|
options: InternalRoomOptions,
|
|
180
187
|
roomRpcHandlers: Map<string, (data: RpcInvocationData) => Promise<string>>,
|
|
181
188
|
roomOutgoingDataStreamManager: OutgoingDataStreamManager,
|
|
189
|
+
roomOutgoingDataTrackManager: OutgoingDataTrackManager,
|
|
182
190
|
) {
|
|
183
191
|
super(sid, identity, undefined, undefined, undefined, {
|
|
184
192
|
loggerName: options.loggerName,
|
|
@@ -198,6 +206,7 @@ export default class LocalParticipant extends Participant {
|
|
|
198
206
|
this.pendingSignalRequests = new Map();
|
|
199
207
|
this.rpcHandlers = roomRpcHandlers;
|
|
200
208
|
this.roomOutgoingDataStreamManager = roomOutgoingDataStreamManager;
|
|
209
|
+
this.roomOutgoingDataTrackManager = roomOutgoingDataTrackManager;
|
|
201
210
|
}
|
|
202
211
|
|
|
203
212
|
get lastCameraError(): Error | undefined {
|
|
@@ -311,6 +320,35 @@ export default class LocalParticipant extends Participant {
|
|
|
311
320
|
}
|
|
312
321
|
this.pendingSignalRequests.delete(requestId);
|
|
313
322
|
}
|
|
323
|
+
|
|
324
|
+
switch (response.request.case) {
|
|
325
|
+
case 'publishDataTrack': {
|
|
326
|
+
let error;
|
|
327
|
+
switch (response.reason) {
|
|
328
|
+
case RequestResponse_Reason.NOT_ALLOWED:
|
|
329
|
+
error = DataTrackPublishError.notAllowed(response.message);
|
|
330
|
+
break;
|
|
331
|
+
case RequestResponse_Reason.DUPLICATE_NAME:
|
|
332
|
+
error = DataTrackPublishError.duplicateName(response.message);
|
|
333
|
+
break;
|
|
334
|
+
case RequestResponse_Reason.INVALID_NAME:
|
|
335
|
+
error = DataTrackPublishError.invalidName(response.message);
|
|
336
|
+
break;
|
|
337
|
+
case RequestResponse_Reason.LIMIT_EXCEEDED:
|
|
338
|
+
error = DataTrackPublishError.limitReached(response.message);
|
|
339
|
+
break;
|
|
340
|
+
default:
|
|
341
|
+
error = DataTrackPublishError.unknown(response.reason, response.message);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
this.roomOutgoingDataTrackManager.receivedSfuPublishResponse(
|
|
346
|
+
response.request.value.pubHandle,
|
|
347
|
+
{ type: 'error', error },
|
|
348
|
+
);
|
|
349
|
+
break;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
314
352
|
};
|
|
315
353
|
|
|
316
354
|
private handleDataPacket = (packet: DataPacket) => {
|
|
@@ -1648,7 +1686,8 @@ export default class LocalParticipant extends Participant {
|
|
|
1648
1686
|
* @param options optionally specify a `reliable`, `topic` and `destination`
|
|
1649
1687
|
*/
|
|
1650
1688
|
async publishData(data: Uint8Array, options: DataPublishOptions = {}): Promise<void> {
|
|
1651
|
-
const kind = options.reliable ?
|
|
1689
|
+
const kind = options.reliable ? DataChannelKind.RELIABLE : DataChannelKind.LOSSY;
|
|
1690
|
+
const dataPacketKind = options.reliable ? DataPacket_Kind.RELIABLE : DataPacket_Kind.LOSSY;
|
|
1652
1691
|
const destinationIdentities = options.destinationIdentities;
|
|
1653
1692
|
const topic = options.topic;
|
|
1654
1693
|
|
|
@@ -1660,7 +1699,7 @@ export default class LocalParticipant extends Participant {
|
|
|
1660
1699
|
});
|
|
1661
1700
|
|
|
1662
1701
|
const packet = new DataPacket({
|
|
1663
|
-
kind:
|
|
1702
|
+
kind: dataPacketKind,
|
|
1664
1703
|
value: {
|
|
1665
1704
|
case: 'user',
|
|
1666
1705
|
value: userPacket,
|
|
@@ -1688,7 +1727,7 @@ export default class LocalParticipant extends Participant {
|
|
|
1688
1727
|
},
|
|
1689
1728
|
});
|
|
1690
1729
|
|
|
1691
|
-
await this.engine.sendDataPacket(packet,
|
|
1730
|
+
await this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
|
|
1692
1731
|
}
|
|
1693
1732
|
|
|
1694
1733
|
/** @deprecated Consider migrating to {@link sendText} */
|
|
@@ -1708,7 +1747,7 @@ export default class LocalParticipant extends Participant {
|
|
|
1708
1747
|
}),
|
|
1709
1748
|
},
|
|
1710
1749
|
});
|
|
1711
|
-
await this.engine.sendDataPacket(packet,
|
|
1750
|
+
await this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
|
|
1712
1751
|
|
|
1713
1752
|
this.emit(ParticipantEvent.ChatMessage, msg);
|
|
1714
1753
|
return msg;
|
|
@@ -1731,7 +1770,7 @@ export default class LocalParticipant extends Participant {
|
|
|
1731
1770
|
}),
|
|
1732
1771
|
},
|
|
1733
1772
|
});
|
|
1734
|
-
await this.engine.sendDataPacket(packet,
|
|
1773
|
+
await this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
|
|
1735
1774
|
this.emit(ParticipantEvent.ChatMessage, msg);
|
|
1736
1775
|
return msg;
|
|
1737
1776
|
}
|
|
@@ -1946,7 +1985,7 @@ export default class LocalParticipant extends Participant {
|
|
|
1946
1985
|
},
|
|
1947
1986
|
});
|
|
1948
1987
|
|
|
1949
|
-
await this.engine.sendDataPacket(packet,
|
|
1988
|
+
await this.engine.sendDataPacket(packet, DataChannelKind.RELIABLE);
|
|
1950
1989
|
}
|
|
1951
1990
|
|
|
1952
1991
|
/** @internal */
|
|
@@ -2235,4 +2274,16 @@ export default class LocalParticipant extends Participant {
|
|
|
2235
2274
|
await sleep(20);
|
|
2236
2275
|
}
|
|
2237
2276
|
}
|
|
2277
|
+
|
|
2278
|
+
/** Publishes a data track.
|
|
2279
|
+
*
|
|
2280
|
+
* Returns the published data track if successful. Use {@link LocalDataTrack#tryPush}
|
|
2281
|
+
* to send data frames on the track.
|
|
2282
|
+
*/
|
|
2283
|
+
async publishDataTrack(options: DataTrackOptions): Promise<LocalDataTrack> {
|
|
2284
|
+
const track = new LocalDataTrack(options, this.roomOutgoingDataTrackManager);
|
|
2285
|
+
await track.publish();
|
|
2286
|
+
|
|
2287
|
+
return track;
|
|
2288
|
+
}
|
|
2238
2289
|
}
|
|
@@ -5,6 +5,8 @@ import type {
|
|
|
5
5
|
UpdateTrackSettings,
|
|
6
6
|
} from '@livekit/protocol';
|
|
7
7
|
import type { SignalClient } from '../../api/SignalClient';
|
|
8
|
+
import { DeferrableMap } from '../../utils/deferrable-map';
|
|
9
|
+
import type RemoteDataTrack from '../data-track/RemoteDataTrack';
|
|
8
10
|
import { ParticipantEvent, TrackEvent } from '../events';
|
|
9
11
|
import RemoteAudioTrack from '../track/RemoteAudioTrack';
|
|
10
12
|
import type RemoteTrack from '../track/RemoteTrack';
|
|
@@ -27,6 +29,14 @@ export default class RemoteParticipant extends Participant {
|
|
|
27
29
|
|
|
28
30
|
trackPublications: Map<string, RemoteTrackPublication>;
|
|
29
31
|
|
|
32
|
+
/** A map of data track name to the corresponding {@link RemoteDataTrack}.
|
|
33
|
+
* @example
|
|
34
|
+
* // An already existing data track:
|
|
35
|
+
* const track = remoteParticipant.dataTracks.get("data track name");
|
|
36
|
+
* // Wait for a data track which will be published soon:
|
|
37
|
+
* const track = await remoteParticipant.dataTracks.getDeferred("data track name"); */
|
|
38
|
+
dataTracks: DeferrableMap<RemoteDataTrack['info']['name'], RemoteDataTrack>;
|
|
39
|
+
|
|
30
40
|
signalClient: SignalClient;
|
|
31
41
|
|
|
32
42
|
private volumeMap: Map<Track.Source, number>;
|
|
@@ -75,6 +85,7 @@ export default class RemoteParticipant extends Participant {
|
|
|
75
85
|
this.trackPublications = new Map();
|
|
76
86
|
this.audioTrackPublications = new Map();
|
|
77
87
|
this.videoTrackPublications = new Map();
|
|
88
|
+
this.dataTracks = new DeferrableMap();
|
|
78
89
|
this.volumeMap = new Map();
|
|
79
90
|
}
|
|
80
91
|
|
|
@@ -376,6 +387,20 @@ export default class RemoteParticipant extends Participant {
|
|
|
376
387
|
await Promise.all(promises);
|
|
377
388
|
}
|
|
378
389
|
|
|
390
|
+
/** @internal */
|
|
391
|
+
addRemoteDataTrack(remoteDataTrack: RemoteDataTrack) {
|
|
392
|
+
this.dataTracks.set(remoteDataTrack.info.name, remoteDataTrack);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/** @internal */
|
|
396
|
+
removeRemoteDataTrack(remoteDataTrackSid: RemoteDataTrack['info']['sid']) {
|
|
397
|
+
for (const [name, dataTrack] of this.dataTracks.entries()) {
|
|
398
|
+
if (remoteDataTrackSid === dataTrack.info.sid) {
|
|
399
|
+
this.dataTracks.delete(name);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
379
404
|
/** @internal */
|
|
380
405
|
emit<E extends keyof ParticipantEventCallbacks>(
|
|
381
406
|
event: E,
|
package/src/room/utils.ts
CHANGED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { type Throws } from '@livekit/throws-transformer/throws';
|
|
2
|
+
import { Future } from '../room/utils';
|
|
3
|
+
|
|
4
|
+
/** An error which is thrown if a {@link DeferrableMap#getDeferred} call is aborted midway
|
|
5
|
+
* through. */
|
|
6
|
+
export class DeferrableMapAbortError extends DOMException {
|
|
7
|
+
reason: unknown;
|
|
8
|
+
|
|
9
|
+
constructor(message: string, reason?: unknown) {
|
|
10
|
+
super(message, 'AbortError');
|
|
11
|
+
this.reason = reason;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A Map-like container keyed by unique strings that supports the ability to wait
|
|
17
|
+
* for future keys to show up in the map.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // An already existing key:
|
|
21
|
+
* const value = map.get("key");
|
|
22
|
+
* // Wait for a key which will be added soon:
|
|
23
|
+
* const value = await map.getDeferred("key");
|
|
24
|
+
*/
|
|
25
|
+
export class DeferrableMap<K, V> extends Map<K, V> {
|
|
26
|
+
private pending: Map<K, Array<Future<V, DeferrableMapAbortError>>> = new Map();
|
|
27
|
+
|
|
28
|
+
set(key: K, value: V): this {
|
|
29
|
+
super.set(key, value);
|
|
30
|
+
|
|
31
|
+
// Resolve any futures waiting on this key.
|
|
32
|
+
const futures = this.pending.get(key);
|
|
33
|
+
if (futures) {
|
|
34
|
+
for (const future of futures) {
|
|
35
|
+
if (!future.isResolved) {
|
|
36
|
+
future.resolve?.(value);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
this.pending.delete(key);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
get [Symbol.toStringTag](): string {
|
|
46
|
+
return 'WaitableMap';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Returns the value for `key` immediately if it exists, otherwise returns a
|
|
51
|
+
* promise that resolves once `set(key, value)` is called.
|
|
52
|
+
*
|
|
53
|
+
* If an `AbortSignal` is provided and it is aborted before the key appears,
|
|
54
|
+
* the returned promise rejects with an {@link DeferrableMapAbortError}.
|
|
55
|
+
*/
|
|
56
|
+
getDeferred(key: K): Promise<V>;
|
|
57
|
+
getDeferred(key: K, signal: AbortSignal): Promise<Throws<V, DeferrableMapAbortError>>;
|
|
58
|
+
async getDeferred(key: K, signal?: AbortSignal) {
|
|
59
|
+
const existing = this.get(key);
|
|
60
|
+
if (typeof existing !== 'undefined') {
|
|
61
|
+
return existing;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Bail out immediately if the signal is already aborted.
|
|
65
|
+
if (signal?.aborted) {
|
|
66
|
+
throw new DeferrableMapAbortError('The operation was aborted.', signal.reason);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const future = new Future<V, DeferrableMapAbortError>(undefined, () => {
|
|
70
|
+
// Clean up the pending list when the future settles.
|
|
71
|
+
const futures = this.pending.get(key);
|
|
72
|
+
if (!futures) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const idx = futures.indexOf(future);
|
|
77
|
+
if (idx !== -1) {
|
|
78
|
+
futures.splice(idx, 1);
|
|
79
|
+
}
|
|
80
|
+
if (futures.length === 0) {
|
|
81
|
+
this.pending.delete(key);
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const existingFutures = this.pending.get(key);
|
|
86
|
+
if (existingFutures) {
|
|
87
|
+
existingFutures.push(future);
|
|
88
|
+
} else {
|
|
89
|
+
this.pending.set(key, [future]);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// If a signal was provided, listen for abort and reject the future.
|
|
93
|
+
if (signal) {
|
|
94
|
+
const onAbort = () => {
|
|
95
|
+
if (!future.isResolved) {
|
|
96
|
+
future.reject?.(new DeferrableMapAbortError('The operation was aborted.', signal.reason));
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
100
|
+
|
|
101
|
+
// Clean up the listener once the future settles (resolved or rejected).
|
|
102
|
+
future.promise.finally(() => {
|
|
103
|
+
signal.removeEventListener('abort', onAbort);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return future.promise;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export type EncryptedPayload = {
|
|
2
|
-
payload: Uint8Array;
|
|
3
|
-
iv: Uint8Array;
|
|
4
|
-
keyIndex: number;
|
|
5
|
-
};
|
|
6
|
-
export type EncryptionProvider = {
|
|
7
|
-
encrypt(payload: Uint8Array): EncryptedPayload;
|
|
8
|
-
};
|
|
9
|
-
export type DecryptionProvider = {
|
|
10
|
-
decrypt(payload: EncryptedPayload, senderIdentity: string): Uint8Array;
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=e2ee.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"e2ee.d.ts","sourceRoot":"","sources":["../../../../src/room/data-track/e2ee.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,UAAU,CAAC;IACpB,EAAE,EAAE,UAAU,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAE/B,OAAO,CAAC,OAAO,EAAE,UAAU,GAAG,gBAAgB,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAE/B,OAAO,CAAC,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,GAAG,UAAU,CAAC;CACxE,CAAC"}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export type EncryptedPayload = {
|
|
2
|
-
payload: Uint8Array;
|
|
3
|
-
iv: Uint8Array;
|
|
4
|
-
keyIndex: number;
|
|
5
|
-
};
|
|
6
|
-
export type EncryptionProvider = {
|
|
7
|
-
encrypt(payload: Uint8Array): EncryptedPayload;
|
|
8
|
-
};
|
|
9
|
-
export type DecryptionProvider = {
|
|
10
|
-
decrypt(payload: EncryptedPayload, senderIdentity: string): Uint8Array;
|
|
11
|
-
};
|
|
12
|
-
//# sourceMappingURL=e2ee.d.ts.map
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export type EncryptedPayload = {
|
|
2
|
-
payload: Uint8Array;
|
|
3
|
-
iv: Uint8Array; // NOTE: should be 12 bytes long
|
|
4
|
-
keyIndex: number;
|
|
5
|
-
};
|
|
6
|
-
|
|
7
|
-
export type EncryptionProvider = {
|
|
8
|
-
// FIXME: add in explicit `Throws<..., EncryptionError>`?
|
|
9
|
-
encrypt(payload: Uint8Array): EncryptedPayload;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
export type DecryptionProvider = {
|
|
13
|
-
// FIXME: add in explicit `Throws<..., DecryptionError>`?
|
|
14
|
-
decrypt(payload: EncryptedPayload, senderIdentity: string): Uint8Array;
|
|
15
|
-
};
|