livekit-client 2.18.0 → 2.18.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 +8 -7
- package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
- package/dist/livekit-client.esm.mjs +8026 -5883
- 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/connectionHelper/ConnectionCheck.d.ts +1 -1
- package/dist/src/connectionHelper/ConnectionCheck.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 +6 -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 +28 -11
- package/dist/src/room/RTCEngine.d.ts.map +1 -1
- package/dist/src/room/Room.d.ts +14 -3
- package/dist/src/room/Room.d.ts.map +1 -1
- package/dist/src/room/data-stream/incoming/IncomingDataStreamManager.d.ts +5 -1
- package/dist/src/room/data-stream/incoming/IncomingDataStreamManager.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 +12 -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/src/utils/serializer.d.ts +48 -0
- package/dist/src/utils/serializer.d.ts.map +1 -0
- package/dist/ts4.2/api/SignalClient.d.ts +12 -4
- package/dist/ts4.2/connectionHelper/ConnectionCheck.d.ts +2 -1
- 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 +7 -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 +28 -11
- package/dist/ts4.2/room/Room.d.ts +14 -3
- package/dist/ts4.2/room/data-stream/incoming/IncomingDataStreamManager.d.ts +5 -1
- 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 +12 -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/dist/ts4.2/utils/serializer.d.ts +48 -0
- package/package.json +1 -1
- package/src/api/SignalClient.test.ts +9 -4
- package/src/api/SignalClient.ts +116 -9
- package/src/connectionHelper/ConnectionCheck.ts +1 -1
- 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 +13 -4
- package/src/room/PCTransport.ts +41 -1
- package/src/room/PCTransportManager.ts +1 -1
- package/src/room/RTCEngine.ts +312 -125
- package/src/room/Room.ts +168 -35
- package/src/room/data-stream/incoming/IncomingDataStreamManager.ts +26 -2
- 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 +139 -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 +74 -8
- package/src/room/participant/RemoteParticipant.ts +25 -0
- package/src/room/utils.ts +4 -0
- package/src/utils/deferrable-map.ts +109 -0
- package/src/utils/serializer.ts +72 -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
|
@@ -1,31 +1,76 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
2
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
|
+
import {
|
|
4
|
+
type DecryptDataResponseMessage,
|
|
5
|
+
type EncryptDataResponseMessage,
|
|
6
|
+
LocalDataTrack,
|
|
7
|
+
} from '../../..';
|
|
8
|
+
import { type BaseE2EEManager } from '../../../e2ee/E2eeManager';
|
|
3
9
|
import { subscribeToEvents } from '../../../utils/subscribeToEvents';
|
|
4
|
-
import
|
|
10
|
+
import RTCEngine from '../../RTCEngine';
|
|
11
|
+
import Room from '../../Room';
|
|
5
12
|
import { DataTrackHandle } from '../handle';
|
|
6
13
|
import { DataTrackPacket, FrameMarker } from '../packet';
|
|
7
14
|
import OutgoingDataTrackManager, {
|
|
8
|
-
DataTrackOutgoingManagerCallbacks,
|
|
15
|
+
type DataTrackOutgoingManagerCallbacks,
|
|
9
16
|
Descriptor,
|
|
10
17
|
} from './OutgoingDataTrackManager';
|
|
11
18
|
import { DataTrackPublishError } from './errors';
|
|
12
19
|
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
/** Fake encryption provider for testing e2ee data track features. */
|
|
21
|
+
export class PrefixingEncryptionProvider implements BaseE2EEManager {
|
|
22
|
+
isEnabled = true;
|
|
23
|
+
|
|
24
|
+
isDataChannelEncryptionEnabled = true;
|
|
25
|
+
|
|
26
|
+
setup(_room: Room) {}
|
|
27
|
+
|
|
28
|
+
setupEngine(_engine: RTCEngine) {}
|
|
29
|
+
|
|
30
|
+
setParticipantCryptorEnabled(_enabled: boolean, _participantIdentity: string) {}
|
|
31
|
+
|
|
32
|
+
setSifTrailer(_trailer: Uint8Array) {}
|
|
33
|
+
|
|
34
|
+
on(_event: any, _listener: any): this {
|
|
35
|
+
return this;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** A fake "encryption" provider used for test purposes. Adds a prefix to the payload. */
|
|
39
|
+
async encryptData(data: Uint8Array): Promise<EncryptDataResponseMessage['data']> {
|
|
16
40
|
const prefix = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);
|
|
17
41
|
|
|
18
|
-
const output = new Uint8Array(prefix.length +
|
|
42
|
+
const output = new Uint8Array(prefix.length + data.length);
|
|
19
43
|
output.set(prefix, 0);
|
|
20
|
-
output.set(
|
|
44
|
+
output.set(data, prefix.length);
|
|
21
45
|
|
|
22
46
|
return {
|
|
47
|
+
uuid: crypto.randomUUID(),
|
|
23
48
|
payload: output,
|
|
24
49
|
iv: new Uint8Array(12), // Just leaving this empty, is this a bad idea?
|
|
25
50
|
keyIndex: 0,
|
|
26
51
|
};
|
|
27
|
-
}
|
|
28
|
-
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** A fake "decryption" provider used for test purposes. Assumes the payload is prefixed with
|
|
55
|
+
* 0xdeafbeef, which is stripped off. */
|
|
56
|
+
async handleEncryptedData(
|
|
57
|
+
payload: Uint8Array,
|
|
58
|
+
_iv: Uint8Array,
|
|
59
|
+
_participantIdentity: string,
|
|
60
|
+
_keyIndex: number,
|
|
61
|
+
): Promise<DecryptDataResponseMessage['data']> {
|
|
62
|
+
if (payload[0] !== 0xde || payload[1] !== 0xad || payload[2] !== 0xbe || payload[3] !== 0xef) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`PrefixingEncryptionProvider: first four bytes of payload were not 0xdeadbeef, found ${payload.slice(0, 4)}`,
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
uuid: crypto.randomUUID(),
|
|
70
|
+
payload: payload.slice(4),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
29
74
|
|
|
30
75
|
describe('DataTrackOutgoingManager', () => {
|
|
31
76
|
it('should test track publishing (ok case)', async () => {
|
|
@@ -34,8 +79,11 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
34
79
|
'sfuPublishRequest',
|
|
35
80
|
]);
|
|
36
81
|
|
|
82
|
+
const localDataTrack = new LocalDataTrack({ name: 'test' }, manager);
|
|
83
|
+
expect(localDataTrack.isPublished()).toStrictEqual(false);
|
|
84
|
+
|
|
37
85
|
// 1. Publish a data track
|
|
38
|
-
const publishRequestPromise =
|
|
86
|
+
const publishRequestPromise = localDataTrack.publish();
|
|
39
87
|
|
|
40
88
|
// 2. This publish request should be sent along to the SFU
|
|
41
89
|
const sfuPublishEvent = await managerEvents.waitFor('sfuPublishRequest');
|
|
@@ -55,7 +103,7 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
55
103
|
});
|
|
56
104
|
|
|
57
105
|
// Make sure that the original input event resolves.
|
|
58
|
-
|
|
106
|
+
await publishRequestPromise;
|
|
59
107
|
expect(localDataTrack.isPublished()).toStrictEqual(true);
|
|
60
108
|
});
|
|
61
109
|
|
|
@@ -66,7 +114,8 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
66
114
|
]);
|
|
67
115
|
|
|
68
116
|
// 1. Publish a data track
|
|
69
|
-
const
|
|
117
|
+
const localDataTrack = new LocalDataTrack({ name: 'test' }, manager);
|
|
118
|
+
const publishRequestPromise = localDataTrack.publish();
|
|
70
119
|
|
|
71
120
|
// 2. This publish request should be sent along to the SFU
|
|
72
121
|
const sfuPublishEvent = await managerEvents.waitFor('sfuPublishRequest');
|
|
@@ -78,7 +127,9 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
78
127
|
});
|
|
79
128
|
|
|
80
129
|
// Make sure that the rejection bubbles back to the caller
|
|
81
|
-
expect(publishRequestPromise).rejects.toThrowError(
|
|
130
|
+
await expect(publishRequestPromise).rejects.toThrowError(
|
|
131
|
+
'Data track publication limit reached',
|
|
132
|
+
);
|
|
82
133
|
});
|
|
83
134
|
|
|
84
135
|
it('should test track publishing (cancellation half way through)', async () => {
|
|
@@ -90,7 +141,8 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
90
141
|
|
|
91
142
|
// 1. Publish a data track
|
|
92
143
|
const controller = new AbortController();
|
|
93
|
-
const
|
|
144
|
+
const localDataTrack = new LocalDataTrack({ name: 'test' }, manager);
|
|
145
|
+
const publishRequestPromise = localDataTrack.publish(controller.signal);
|
|
94
146
|
|
|
95
147
|
// 2. This publish request should be sent along to the SFU
|
|
96
148
|
const sfuPublishEvent = await managerEvents.waitFor('sfuPublishRequest');
|
|
@@ -107,7 +159,7 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
107
159
|
expect(sfuUnpublishEvent.handle).toStrictEqual(handle);
|
|
108
160
|
|
|
109
161
|
// 5. Make sure cancellation is bubbled up as an error to stop further execution
|
|
110
|
-
expect(publishRequestPromise).rejects.toStrictEqual(DataTrackPublishError.cancelled());
|
|
162
|
+
await expect(publishRequestPromise).rejects.toStrictEqual(DataTrackPublishError.cancelled());
|
|
111
163
|
});
|
|
112
164
|
|
|
113
165
|
it('should test track publishing (cancellation before it starts)', async () => {
|
|
@@ -118,18 +170,87 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
118
170
|
]);
|
|
119
171
|
|
|
120
172
|
// Publish a data track
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
AbortSignal.abort(/* already aborted */),
|
|
124
|
-
);
|
|
173
|
+
const localDataTrack = new LocalDataTrack({ name: 'test' }, manager);
|
|
174
|
+
const publishRequestPromise = localDataTrack.publish(AbortSignal.abort(/* already aborted */));
|
|
125
175
|
|
|
126
176
|
// Make sure cancellation is immediately bubbled up
|
|
127
|
-
expect(publishRequestPromise).rejects.toStrictEqual(DataTrackPublishError.cancelled());
|
|
177
|
+
await expect(publishRequestPromise).rejects.toStrictEqual(DataTrackPublishError.cancelled());
|
|
128
178
|
|
|
129
179
|
// And there were no pending sfu publish requests sent
|
|
130
180
|
expect(managerEvents.areThereBufferedEvents('sfuPublishRequest')).toBe(false);
|
|
131
181
|
});
|
|
132
182
|
|
|
183
|
+
it('should test track publishing, unpublishing, and republishing again', async () => {
|
|
184
|
+
const manager = new OutgoingDataTrackManager();
|
|
185
|
+
const managerEvents = subscribeToEvents<DataTrackOutgoingManagerCallbacks>(manager, [
|
|
186
|
+
'sfuPublishRequest',
|
|
187
|
+
'sfuUnpublishRequest',
|
|
188
|
+
]);
|
|
189
|
+
|
|
190
|
+
// 1. Create a local data track
|
|
191
|
+
const localDataTrack = new LocalDataTrack({ name: 'test' }, manager);
|
|
192
|
+
expect(localDataTrack.isPublished()).toStrictEqual(false);
|
|
193
|
+
|
|
194
|
+
// 2. Publish it
|
|
195
|
+
const publishRequestPromise = localDataTrack.publish();
|
|
196
|
+
|
|
197
|
+
// 3. This publish request should be sent along to the SFU
|
|
198
|
+
const sfuPublishEvent = await managerEvents.waitFor('sfuPublishRequest');
|
|
199
|
+
expect(sfuPublishEvent.name).toStrictEqual('test');
|
|
200
|
+
expect(sfuPublishEvent.usesE2ee).toStrictEqual(false);
|
|
201
|
+
const handle = sfuPublishEvent.handle;
|
|
202
|
+
|
|
203
|
+
// 4. Respond to the SFU publish request with an OK response
|
|
204
|
+
manager.receivedSfuPublishResponse(handle, {
|
|
205
|
+
type: 'ok',
|
|
206
|
+
data: {
|
|
207
|
+
sid: 'bogus-sid',
|
|
208
|
+
pubHandle: sfuPublishEvent.handle,
|
|
209
|
+
name: 'test',
|
|
210
|
+
usesE2ee: false,
|
|
211
|
+
},
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// Make sure that the original input event resolves.
|
|
215
|
+
await publishRequestPromise;
|
|
216
|
+
|
|
217
|
+
// 5. Now the data track should be published
|
|
218
|
+
expect(localDataTrack.isPublished()).toStrictEqual(true);
|
|
219
|
+
|
|
220
|
+
// 6. Unpublish the data track
|
|
221
|
+
const unpublishRequestPromise = localDataTrack.unpublish();
|
|
222
|
+
const sfuUnpublishEvent = await managerEvents.waitFor('sfuUnpublishRequest');
|
|
223
|
+
manager.receivedSfuUnpublishResponse(sfuUnpublishEvent.handle);
|
|
224
|
+
await unpublishRequestPromise;
|
|
225
|
+
|
|
226
|
+
// 7. Now the data track should be unpublished
|
|
227
|
+
expect(localDataTrack.isPublished()).toStrictEqual(false);
|
|
228
|
+
|
|
229
|
+
// 8. Now, republish the track and make sure that be done a second time
|
|
230
|
+
const publishRequestPromise2 = localDataTrack.publish();
|
|
231
|
+
const sfuPublishEvent2 = await managerEvents.waitFor('sfuPublishRequest');
|
|
232
|
+
expect(sfuPublishEvent2.name).toStrictEqual('test');
|
|
233
|
+
expect(sfuPublishEvent2.usesE2ee).toStrictEqual(false);
|
|
234
|
+
const handle2 = sfuPublishEvent2.handle;
|
|
235
|
+
manager.receivedSfuPublishResponse(handle2, {
|
|
236
|
+
type: 'ok',
|
|
237
|
+
data: {
|
|
238
|
+
sid: 'bogus-sid',
|
|
239
|
+
pubHandle: sfuPublishEvent2.handle,
|
|
240
|
+
name: 'test',
|
|
241
|
+
usesE2ee: false,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
await publishRequestPromise2;
|
|
245
|
+
|
|
246
|
+
// 9. Ensure that the track is published again
|
|
247
|
+
expect(localDataTrack.isPublished()).toStrictEqual(true);
|
|
248
|
+
|
|
249
|
+
// 10. Also ensure that the handle used on the second publish attempt differs from the first
|
|
250
|
+
// publish attempt.
|
|
251
|
+
expect(handle).not.toStrictEqual(handle2);
|
|
252
|
+
});
|
|
253
|
+
|
|
133
254
|
it.each([
|
|
134
255
|
// Single packet payload case
|
|
135
256
|
[
|
|
@@ -207,18 +328,17 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
207
328
|
]),
|
|
208
329
|
);
|
|
209
330
|
const managerEvents = subscribeToEvents<DataTrackOutgoingManagerCallbacks>(manager, [
|
|
210
|
-
'
|
|
331
|
+
'packetAvailable',
|
|
211
332
|
]);
|
|
212
333
|
|
|
213
|
-
const localDataTrack =
|
|
214
|
-
expect(localDataTrack).not.toStrictEqual(null);
|
|
334
|
+
const localDataTrack = LocalDataTrack.withExplicitHandle({ name: 'track name' }, manager, 5);
|
|
215
335
|
|
|
216
336
|
// Kick off sending the bytes...
|
|
217
|
-
localDataTrack.tryPush(inputBytes);
|
|
337
|
+
localDataTrack.tryPush({ payload: inputBytes });
|
|
218
338
|
|
|
219
339
|
// ... and make sure the corresponding events are emitted to tell the SFU to send the packets
|
|
220
340
|
for (const outputPacketJson of outputPacketsJson) {
|
|
221
|
-
const packetBytes = await managerEvents.waitFor('
|
|
341
|
+
const packetBytes = await managerEvents.waitFor('packetAvailable');
|
|
222
342
|
const [packet] = DataTrackPacket.fromBinary(packetBytes.bytes);
|
|
223
343
|
|
|
224
344
|
expect(packet.toJSON()).toStrictEqual(outputPacketJson);
|
|
@@ -228,15 +348,16 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
228
348
|
|
|
229
349
|
it('should send e2ee encrypted datatrack payload', async () => {
|
|
230
350
|
const manager = new OutgoingDataTrackManager({
|
|
231
|
-
|
|
351
|
+
e2eeManager: new PrefixingEncryptionProvider(),
|
|
232
352
|
});
|
|
233
353
|
const managerEvents = subscribeToEvents<DataTrackOutgoingManagerCallbacks>(manager, [
|
|
234
354
|
'sfuPublishRequest',
|
|
235
|
-
'
|
|
355
|
+
'packetAvailable',
|
|
236
356
|
]);
|
|
237
357
|
|
|
238
358
|
// 1. Publish a data track
|
|
239
|
-
const
|
|
359
|
+
const localDataTrack = new LocalDataTrack({ name: 'test' }, manager);
|
|
360
|
+
const publishRequestPromise = localDataTrack.publish();
|
|
240
361
|
|
|
241
362
|
// 2. This publish request should be sent along to the SFU
|
|
242
363
|
const sfuPublishEvent = await managerEvents.waitFor('sfuPublishRequest');
|
|
@@ -256,14 +377,14 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
256
377
|
});
|
|
257
378
|
|
|
258
379
|
// Get the connected local data track
|
|
259
|
-
|
|
380
|
+
await publishRequestPromise;
|
|
260
381
|
expect(localDataTrack.isPublished()).toStrictEqual(true);
|
|
261
382
|
|
|
262
383
|
// Kick off sending the payload bytes
|
|
263
|
-
localDataTrack.tryPush(new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05]));
|
|
384
|
+
localDataTrack.tryPush({ payload: new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05]) });
|
|
264
385
|
|
|
265
386
|
// Make sure the packet that was sent was encrypted with the PrefixingEncryptionProvider
|
|
266
|
-
const packetBytes = await managerEvents.waitFor('
|
|
387
|
+
const packetBytes = await managerEvents.waitFor('packetAvailable');
|
|
267
388
|
const [packet] = DataTrackPacket.fromBinary(packetBytes.bytes);
|
|
268
389
|
|
|
269
390
|
expect(packet.toJSON()).toStrictEqual({
|
|
@@ -331,6 +452,76 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
331
452
|
expect(manager.getDescriptor(5)).toStrictEqual(null);
|
|
332
453
|
});
|
|
333
454
|
|
|
455
|
+
it('should test a full reconnect', async () => {
|
|
456
|
+
const pubHandle = 5;
|
|
457
|
+
// Create a manager prefilled with a descriptor
|
|
458
|
+
const manager = OutgoingDataTrackManager.withDescriptors(
|
|
459
|
+
new Map([
|
|
460
|
+
[
|
|
461
|
+
DataTrackHandle.fromNumber(5),
|
|
462
|
+
Descriptor.active(
|
|
463
|
+
{
|
|
464
|
+
sid: 'bogus-sid',
|
|
465
|
+
pubHandle,
|
|
466
|
+
name: 'test',
|
|
467
|
+
usesE2ee: false,
|
|
468
|
+
},
|
|
469
|
+
null,
|
|
470
|
+
),
|
|
471
|
+
],
|
|
472
|
+
]),
|
|
473
|
+
);
|
|
474
|
+
const managerEvents = subscribeToEvents<DataTrackOutgoingManagerCallbacks>(manager, [
|
|
475
|
+
'sfuPublishRequest',
|
|
476
|
+
'packetAvailable',
|
|
477
|
+
'sfuUnpublishRequest',
|
|
478
|
+
]);
|
|
479
|
+
const localDataTrack = LocalDataTrack.withExplicitHandle({ name: 'track name' }, manager, 5);
|
|
480
|
+
|
|
481
|
+
// Make sure the descriptor is in there
|
|
482
|
+
expect(manager.getDescriptor(5)?.type).toStrictEqual('active');
|
|
483
|
+
|
|
484
|
+
// Simulate a full reconnect, which means that any published tracks will need to be republished.
|
|
485
|
+
manager.sfuWillRepublishTracks();
|
|
486
|
+
|
|
487
|
+
// Even though behind the scenes the SFU publications are not active, the user should still see
|
|
488
|
+
// it as "published", sfu reconnects are an implementation detail
|
|
489
|
+
expect(localDataTrack.isPublished()).toStrictEqual(true);
|
|
490
|
+
|
|
491
|
+
// But, even though `isPublished` is true, pushing data should drop (no sfu to send them to!)
|
|
492
|
+
await expect(() =>
|
|
493
|
+
localDataTrack.tryPush({ payload: new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05]) }),
|
|
494
|
+
).rejects.toThrowError('Frame was dropped');
|
|
495
|
+
|
|
496
|
+
// 2. This publish request should be sent along to the SFU
|
|
497
|
+
const sfuPublishEvent = await managerEvents.waitFor('sfuPublishRequest');
|
|
498
|
+
expect(sfuPublishEvent.name).toStrictEqual('test');
|
|
499
|
+
expect(sfuPublishEvent.usesE2ee).toStrictEqual(false);
|
|
500
|
+
const handle = sfuPublishEvent.handle;
|
|
501
|
+
expect(handle).toStrictEqual(pubHandle);
|
|
502
|
+
|
|
503
|
+
// 3. Respond to the SFU publish request with an OK response
|
|
504
|
+
manager.receivedSfuPublishResponse(handle, {
|
|
505
|
+
type: 'ok',
|
|
506
|
+
data: {
|
|
507
|
+
sid: 'bogus-sid-REPUBLISHED',
|
|
508
|
+
pubHandle: sfuPublishEvent.handle,
|
|
509
|
+
name: 'test',
|
|
510
|
+
usesE2ee: false,
|
|
511
|
+
},
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
// After all this, the local data track should still be published
|
|
515
|
+
expect(localDataTrack.isPublished()).toStrictEqual(true);
|
|
516
|
+
|
|
517
|
+
// And the sid should be the new value
|
|
518
|
+
expect(localDataTrack.info!.sid).toStrictEqual('bogus-sid-REPUBLISHED');
|
|
519
|
+
|
|
520
|
+
// And now that the tracks are backed by the SFU again, pushes should function!
|
|
521
|
+
await localDataTrack.tryPush({ payload: new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05]) });
|
|
522
|
+
await managerEvents.waitFor('packetAvailable');
|
|
523
|
+
});
|
|
524
|
+
|
|
334
525
|
it('should query currently active descriptors', async () => {
|
|
335
526
|
// Create a manager prefilled with a descriptor
|
|
336
527
|
const manager = OutgoingDataTrackManager.withDescriptors(
|
|
@@ -398,7 +589,9 @@ describe('DataTrackOutgoingManager', () => {
|
|
|
398
589
|
const shutdownPromise = manager.shutdown();
|
|
399
590
|
|
|
400
591
|
// The pending data track should be cancelled
|
|
401
|
-
expect(pendingDescriptor.completionFuture.promise).rejects.toThrowError(
|
|
592
|
+
await expect(pendingDescriptor.completionFuture.promise).rejects.toThrowError(
|
|
593
|
+
'Room disconnected',
|
|
594
|
+
);
|
|
402
595
|
|
|
403
596
|
// And the active data track should be requested to be unpublished
|
|
404
597
|
const unpublishEvent = await managerEvents.waitFor('sfuUnpublishRequest');
|