livekit-client 2.17.3 → 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.
Files changed (183) hide show
  1. package/dist/livekit-client.e2ee.worker.js +1 -1
  2. package/dist/livekit-client.e2ee.worker.js.map +1 -1
  3. package/dist/livekit-client.e2ee.worker.mjs +8 -7
  4. package/dist/livekit-client.e2ee.worker.mjs.map +1 -1
  5. package/dist/livekit-client.esm.mjs +7823 -5772
  6. package/dist/livekit-client.esm.mjs.map +1 -1
  7. package/dist/livekit-client.umd.js +1 -1
  8. package/dist/livekit-client.umd.js.map +1 -1
  9. package/dist/src/api/SignalClient.d.ts +12 -4
  10. package/dist/src/api/SignalClient.d.ts.map +1 -1
  11. package/dist/src/e2ee/constants.d.ts.map +1 -1
  12. package/dist/src/e2ee/types.d.ts +6 -0
  13. package/dist/src/e2ee/types.d.ts.map +1 -1
  14. package/dist/src/e2ee/utils.d.ts +2 -1
  15. package/dist/src/e2ee/utils.d.ts.map +1 -1
  16. package/dist/src/e2ee/worker/DataCryptor.d.ts.map +1 -1
  17. package/dist/src/e2ee/worker/FrameCryptor.d.ts.map +1 -1
  18. package/dist/src/index.d.ts +5 -4
  19. package/dist/src/index.d.ts.map +1 -1
  20. package/dist/src/room/PCTransport.d.ts +5 -0
  21. package/dist/src/room/PCTransport.d.ts.map +1 -1
  22. package/dist/src/room/PCTransportManager.d.ts +1 -1
  23. package/dist/src/room/PCTransportManager.d.ts.map +1 -1
  24. package/dist/src/room/RTCEngine.d.ts +27 -9
  25. package/dist/src/room/RTCEngine.d.ts.map +1 -1
  26. package/dist/src/room/Room.d.ts +13 -3
  27. package/dist/src/room/Room.d.ts.map +1 -1
  28. package/dist/src/room/data-stream/outgoing/OutgoingDataStreamManager.d.ts.map +1 -1
  29. package/dist/src/room/data-track/LocalDataTrack.d.ts +48 -0
  30. package/dist/src/room/data-track/LocalDataTrack.d.ts.map +1 -0
  31. package/dist/src/room/data-track/RemoteDataTrack.d.ts +46 -0
  32. package/dist/src/room/data-track/RemoteDataTrack.d.ts.map +1 -0
  33. package/dist/src/room/data-track/depacketizer.d.ts +6 -6
  34. package/dist/src/room/data-track/depacketizer.d.ts.map +1 -1
  35. package/dist/src/room/data-track/frame.d.ts +14 -0
  36. package/dist/src/room/data-track/frame.d.ts.map +1 -1
  37. package/dist/src/room/data-track/handle.d.ts +2 -2
  38. package/dist/src/room/data-track/handle.d.ts.map +1 -1
  39. package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts +104 -0
  40. package/dist/src/room/data-track/incoming/IncomingDataTrackManager.d.ts.map +1 -0
  41. package/dist/src/room/data-track/incoming/errors.d.ts +24 -0
  42. package/dist/src/room/data-track/incoming/errors.d.ts.map +1 -0
  43. package/dist/src/room/data-track/incoming/pipeline.d.ts +38 -0
  44. package/dist/src/room/data-track/incoming/pipeline.d.ts.map +1 -0
  45. package/dist/src/room/data-track/incoming/types.d.ts +20 -0
  46. package/dist/src/room/data-track/incoming/types.d.ts.map +1 -0
  47. package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +63 -28
  48. package/dist/src/room/data-track/outgoing/OutgoingDataTrackManager.d.ts.map +1 -1
  49. package/dist/src/room/data-track/outgoing/errors.d.ts +20 -10
  50. package/dist/src/room/data-track/outgoing/errors.d.ts.map +1 -1
  51. package/dist/src/room/data-track/outgoing/pipeline.d.ts +9 -8
  52. package/dist/src/room/data-track/outgoing/pipeline.d.ts.map +1 -1
  53. package/dist/src/room/data-track/outgoing/types.d.ts +16 -7
  54. package/dist/src/room/data-track/outgoing/types.d.ts.map +1 -1
  55. package/dist/src/room/data-track/packet/errors.d.ts +2 -4
  56. package/dist/src/room/data-track/packet/errors.d.ts.map +1 -1
  57. package/dist/src/room/data-track/packet/extensions.d.ts +4 -4
  58. package/dist/src/room/data-track/packet/extensions.d.ts.map +1 -1
  59. package/dist/src/room/data-track/packet/index.d.ts +5 -5
  60. package/dist/src/room/data-track/packet/index.d.ts.map +1 -1
  61. package/dist/src/room/data-track/packet/serializable.d.ts +4 -4
  62. package/dist/src/room/data-track/packet/serializable.d.ts.map +1 -1
  63. package/dist/src/room/data-track/packetizer.d.ts +6 -6
  64. package/dist/src/room/data-track/packetizer.d.ts.map +1 -1
  65. package/dist/src/room/data-track/track-interfaces.d.ts +23 -0
  66. package/dist/src/room/data-track/track-interfaces.d.ts.map +1 -0
  67. package/dist/src/room/data-track/types.d.ts +15 -0
  68. package/dist/src/room/data-track/types.d.ts.map +1 -0
  69. package/dist/src/room/events.d.ts +24 -3
  70. package/dist/src/room/events.d.ts.map +1 -1
  71. package/dist/src/room/participant/LocalParticipant.d.ts +11 -1
  72. package/dist/src/room/participant/LocalParticipant.d.ts.map +1 -1
  73. package/dist/src/room/participant/RemoteParticipant.d.ts +14 -1
  74. package/dist/src/room/participant/RemoteParticipant.d.ts.map +1 -1
  75. package/dist/src/room/token-source/TokenSource.d.ts +1 -1
  76. package/dist/src/room/token-source/TokenSource.d.ts.map +1 -1
  77. package/dist/src/room/token-source/types.d.ts +1 -0
  78. package/dist/src/room/token-source/types.d.ts.map +1 -1
  79. package/dist/src/room/utils.d.ts +2 -1
  80. package/dist/src/room/utils.d.ts.map +1 -1
  81. package/dist/src/utils/abort-signal-polyfill.d.ts +13 -0
  82. package/dist/src/utils/abort-signal-polyfill.d.ts.map +1 -0
  83. package/dist/src/utils/deferrable-map.d.ts +32 -0
  84. package/dist/src/utils/deferrable-map.d.ts.map +1 -0
  85. package/dist/src/utils/subscribeToEvents.d.ts +3 -0
  86. package/dist/src/utils/subscribeToEvents.d.ts.map +1 -1
  87. package/dist/ts4.2/api/SignalClient.d.ts +12 -4
  88. package/dist/ts4.2/e2ee/types.d.ts +6 -0
  89. package/dist/ts4.2/e2ee/utils.d.ts +2 -1
  90. package/dist/ts4.2/index.d.ts +5 -4
  91. package/dist/ts4.2/room/PCTransport.d.ts +5 -0
  92. package/dist/ts4.2/room/PCTransportManager.d.ts +1 -1
  93. package/dist/ts4.2/room/RTCEngine.d.ts +27 -9
  94. package/dist/ts4.2/room/Room.d.ts +13 -3
  95. package/dist/ts4.2/room/data-track/LocalDataTrack.d.ts +48 -0
  96. package/dist/ts4.2/room/data-track/RemoteDataTrack.d.ts +46 -0
  97. package/dist/ts4.2/room/data-track/depacketizer.d.ts +6 -6
  98. package/dist/ts4.2/room/data-track/frame.d.ts +14 -0
  99. package/dist/ts4.2/room/data-track/handle.d.ts +2 -2
  100. package/dist/ts4.2/room/data-track/incoming/IncomingDataTrackManager.d.ts +110 -0
  101. package/dist/ts4.2/room/data-track/incoming/errors.d.ts +24 -0
  102. package/dist/ts4.2/room/data-track/incoming/pipeline.d.ts +38 -0
  103. package/dist/ts4.2/room/data-track/incoming/types.d.ts +20 -0
  104. package/dist/ts4.2/room/data-track/outgoing/OutgoingDataTrackManager.d.ts +63 -29
  105. package/dist/ts4.2/room/data-track/outgoing/errors.d.ts +20 -10
  106. package/dist/ts4.2/room/data-track/outgoing/pipeline.d.ts +9 -8
  107. package/dist/ts4.2/room/data-track/outgoing/types.d.ts +16 -7
  108. package/dist/ts4.2/room/data-track/packet/errors.d.ts +2 -4
  109. package/dist/ts4.2/room/data-track/packet/extensions.d.ts +4 -4
  110. package/dist/ts4.2/room/data-track/packet/index.d.ts +5 -6
  111. package/dist/ts4.2/room/data-track/packet/serializable.d.ts +4 -4
  112. package/dist/ts4.2/room/data-track/packetizer.d.ts +6 -6
  113. package/dist/ts4.2/room/data-track/track-interfaces.d.ts +23 -0
  114. package/dist/ts4.2/room/data-track/types.d.ts +15 -0
  115. package/dist/ts4.2/room/events.d.ts +24 -3
  116. package/dist/ts4.2/room/participant/LocalParticipant.d.ts +11 -1
  117. package/dist/ts4.2/room/participant/RemoteParticipant.d.ts +14 -1
  118. package/dist/ts4.2/room/token-source/TokenSource.d.ts +1 -1
  119. package/dist/ts4.2/room/token-source/types.d.ts +1 -0
  120. package/dist/ts4.2/room/utils.d.ts +2 -1
  121. package/dist/ts4.2/utils/abort-signal-polyfill.d.ts +13 -0
  122. package/dist/ts4.2/utils/deferrable-map.d.ts +32 -0
  123. package/dist/ts4.2/utils/subscribeToEvents.d.ts +3 -0
  124. package/package.json +4 -2
  125. package/src/api/SignalClient.test.ts +9 -4
  126. package/src/api/SignalClient.ts +116 -9
  127. package/src/e2ee/constants.ts +1 -0
  128. package/src/e2ee/types.ts +6 -0
  129. package/src/e2ee/utils.ts +4 -3
  130. package/src/e2ee/worker/DataCryptor.ts +1 -4
  131. package/src/e2ee/worker/FrameCryptor.ts +1 -4
  132. package/src/e2ee/worker/ParticipantKeyHandler.ts +1 -1
  133. package/src/index.ts +6 -4
  134. package/src/room/PCTransport.ts +41 -1
  135. package/src/room/PCTransportManager.ts +1 -1
  136. package/src/room/RTCEngine.ts +274 -112
  137. package/src/room/Room.ts +152 -15
  138. package/src/room/data-stream/outgoing/OutgoingDataStreamManager.ts +9 -9
  139. package/src/room/data-track/LocalDataTrack.ts +126 -0
  140. package/src/room/data-track/RemoteDataTrack.ts +80 -0
  141. package/src/room/data-track/depacketizer.ts +23 -26
  142. package/src/room/data-track/frame.ts +28 -2
  143. package/src/room/data-track/handle.ts +2 -8
  144. package/src/room/data-track/incoming/IncomingDataTrackManager.test.ts +555 -0
  145. package/src/room/data-track/incoming/IncomingDataTrackManager.ts +589 -0
  146. package/src/room/data-track/incoming/errors.ts +57 -0
  147. package/src/room/data-track/incoming/pipeline.ts +121 -0
  148. package/src/room/data-track/incoming/types.ts +22 -0
  149. package/src/room/data-track/outgoing/OutgoingDataTrackManager.test.ts +240 -27
  150. package/src/room/data-track/outgoing/OutgoingDataTrackManager.ts +165 -84
  151. package/src/room/data-track/outgoing/errors.ts +40 -11
  152. package/src/room/data-track/outgoing/pipeline.ts +25 -23
  153. package/src/room/data-track/outgoing/types.ts +14 -6
  154. package/src/room/data-track/packet/errors.ts +2 -14
  155. package/src/room/data-track/packet/extensions.ts +21 -26
  156. package/src/room/data-track/packet/index.test.ts +22 -33
  157. package/src/room/data-track/packet/index.ts +4 -6
  158. package/src/room/data-track/packet/serializable.ts +4 -4
  159. package/src/room/data-track/packetizer.test.ts +2 -2
  160. package/src/room/data-track/packetizer.ts +7 -10
  161. package/src/room/data-track/track-interfaces.ts +53 -0
  162. package/src/room/data-track/types.ts +31 -0
  163. package/src/room/events.ts +26 -1
  164. package/src/room/participant/LocalParticipant.ts +57 -6
  165. package/src/room/participant/RemoteParticipant.ts +26 -1
  166. package/src/room/token-source/TokenSource.ts +8 -2
  167. package/src/room/token-source/types.ts +4 -0
  168. package/src/room/utils.ts +5 -1
  169. package/src/utils/abort-signal-polyfill.ts +63 -0
  170. package/src/utils/deferrable-map.ts +109 -0
  171. package/src/utils/subscribeToEvents.ts +18 -1
  172. package/dist/src/room/data-track/e2ee.d.ts +0 -12
  173. package/dist/src/room/data-track/e2ee.d.ts.map +0 -1
  174. package/dist/src/room/data-track/track.d.ts +0 -30
  175. package/dist/src/room/data-track/track.d.ts.map +0 -1
  176. package/dist/src/utils/throws.d.ts +0 -36
  177. package/dist/src/utils/throws.d.ts.map +0 -1
  178. package/dist/ts4.2/room/data-track/e2ee.d.ts +0 -12
  179. package/dist/ts4.2/room/data-track/track.d.ts +0 -30
  180. package/dist/ts4.2/utils/throws.d.ts +0 -39
  181. package/src/room/data-track/e2ee.ts +0 -14
  182. package/src/room/data-track/track.ts +0 -50
  183. package/src/utils/throws.ts +0 -42
@@ -8,6 +8,7 @@ import {
8
8
  DataChannelReceiveState,
9
9
  DataPacket,
10
10
  DataPacket_Kind,
11
+ DataTrackSubscriberHandles,
11
12
  DisconnectReason,
12
13
  EncryptedPacket,
13
14
  EncryptedPacketPayload,
@@ -17,6 +18,7 @@ import {
17
18
  LeaveRequest_Action,
18
19
  MediaSectionsRequirement,
19
20
  ParticipantInfo,
21
+ PublishDataTrackResponse,
20
22
  ReconnectReason,
21
23
  type ReconnectResponse,
22
24
  RequestResponse,
@@ -24,6 +26,7 @@ import {
24
26
  RoomMovedResponse,
25
27
  RpcAck,
26
28
  RpcResponse,
29
+ SessionDescription,
27
30
  SignalTarget,
28
31
  SpeakerInfo,
29
32
  type StreamStateUpdate,
@@ -35,6 +38,7 @@ import {
35
38
  type TrackPublishedResponse,
36
39
  TrackUnpublishedResponse,
37
40
  Transcription,
41
+ UnpublishDataTrackResponse,
38
42
  UpdateSubscription,
39
43
  type UserPacket,
40
44
  } from '@livekit/protocol';
@@ -58,6 +62,7 @@ import PCTransport, { PCEvents } from './PCTransport';
58
62
  import { PCTransportManager, PCTransportState } from './PCTransportManager';
59
63
  import type { ReconnectContext, ReconnectPolicy } from './ReconnectPolicy';
60
64
  import { DEFAULT_MAX_AGE_MS, type RegionUrlProvider } from './RegionUrlProvider';
65
+ import { DataTrackInfo } from './data-track/types';
61
66
  import { roomConnectOptionDefaults } from './defaults';
62
67
  import {
63
68
  ConnectionError,
@@ -80,6 +85,7 @@ import type { TrackPublishOptions, VideoCodec } from './track/options';
80
85
  import { getTrackPublicationInfo } from './track/utils';
81
86
  import type { LoggerOptions } from './types';
82
87
  import {
88
+ isCompressionStreamSupported,
83
89
  isVideoCodec,
84
90
  isVideoTrack,
85
91
  isWeb,
@@ -91,11 +97,14 @@ import {
91
97
 
92
98
  const lossyDataChannel = '_lossy';
93
99
  const reliableDataChannel = '_reliable';
100
+ const dataTrackDataChannel = '_data_track';
94
101
  const minReconnectWait = 2 * 1000;
95
102
  const leaveReconnect = 'leave-reconnect';
96
103
  const reliabeReceiveStateTTL = 30_000;
97
104
  const lossyDataChannelBufferThresholdMin = 8 * 1024;
98
105
  const lossyDataChannelBufferThresholdMax = 256 * 1024;
106
+ const initialMediaSectionsAudio = 3;
107
+ const initialMediaSectionsVideo = 3;
99
108
 
100
109
  enum PCState {
101
110
  New,
@@ -105,6 +114,12 @@ enum PCState {
105
114
  Closed,
106
115
  }
107
116
 
117
+ export enum DataChannelKind {
118
+ RELIABLE = DataPacket_Kind.RELIABLE,
119
+ LOSSY = DataPacket_Kind.LOSSY,
120
+ DATA_TRACK_LOSSY,
121
+ }
122
+
108
123
  /** @internal */
109
124
  export default class RTCEngine extends (EventEmitter as new () => TypedEventEmitter<EngineEventCallbacks>) {
110
125
  client: SignalClient;
@@ -134,6 +149,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
134
149
  return this._isClosed;
135
150
  }
136
151
 
152
+ get isNewlyCreated() {
153
+ return this._isNewlyCreated;
154
+ }
155
+
137
156
  get pendingReconnect() {
138
157
  return !!this.reconnectTimeout;
139
158
  }
@@ -145,17 +164,24 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
145
164
 
146
165
  private reliableDC?: RTCDataChannel;
147
166
 
148
- private dcBufferStatus: Map<DataPacket_Kind, boolean>;
149
-
150
167
  // @ts-ignore noUnusedLocals
151
168
  private reliableDCSub?: RTCDataChannel;
152
169
 
170
+ private dataTrackDC?: RTCDataChannel;
171
+
172
+ // @ts-ignore noUnusedLocals
173
+ private dataTrackDCSub?: RTCDataChannel;
174
+
175
+ private dcBufferStatus: Map<DataChannelKind, boolean>;
176
+
153
177
  private subscriberPrimary: boolean = false;
154
178
 
155
179
  private pcState: PCState = PCState.New;
156
180
 
157
181
  private _isClosed: boolean = true;
158
182
 
183
+ private _isNewlyCreated: boolean = true;
184
+
159
185
  private pendingTrackResolvers: {
160
186
  [key: string]: { resolve: (info: TrackInfo) => void; reject: () => void };
161
187
  } = {};
@@ -233,8 +259,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
233
259
  this.closingLock = new Mutex();
234
260
  this.dataProcessLock = new Mutex();
235
261
  this.dcBufferStatus = new Map([
236
- [DataPacket_Kind.LOSSY, true],
237
- [DataPacket_Kind.RELIABLE, true],
262
+ [DataChannelKind.RELIABLE, true],
263
+ [DataChannelKind.LOSSY, true],
264
+ [DataChannelKind.DATA_TRACK_LOSSY, true],
238
265
  ]);
239
266
 
240
267
  this.client.onParticipantUpdate = (updates) =>
@@ -249,6 +276,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
249
276
  this.client.onStreamStateUpdate = (update) => this.emit(EngineEvent.StreamStateChanged, update);
250
277
  this.client.onRequestResponse = (response) =>
251
278
  this.emit(EngineEvent.SignalRequestResponse, response);
279
+ this.client.onParticipantUpdate = (updates) =>
280
+ this.emit(EngineEvent.ParticipantUpdate, updates);
281
+ this.client.onJoined = (joinResponse) => this.emit(EngineEvent.Joined, joinResponse);
252
282
  }
253
283
 
254
284
  /** @internal */
@@ -257,7 +287,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
257
287
  room: this.latestJoinResponse?.room?.name,
258
288
  roomID: this.latestJoinResponse?.room?.sid,
259
289
  participant: this.latestJoinResponse?.participant?.identity,
260
- pID: this.participantSid,
290
+ participantID: this.participantSid,
261
291
  };
262
292
  }
263
293
 
@@ -269,6 +299,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
269
299
  /** setting this to true results in dual peer connection mode being used */
270
300
  useV0Path: boolean = false,
271
301
  ): Promise<JoinResponse> {
302
+ this._isNewlyCreated = false;
272
303
  this.url = url;
273
304
  this.token = token;
274
305
  this.signalOpts = opts;
@@ -277,20 +308,46 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
277
308
  this.joinAttempts += 1;
278
309
 
279
310
  this.setupSignalClientCallbacks();
280
- const joinResponse = await this.client.join(url, token, opts, abortSignal, useV0Path);
311
+ let offerProto: SessionDescription | undefined;
312
+ if (!useV0Path && isCompressionStreamSupported()) {
313
+ if (!this.pcManager) {
314
+ await this.configure();
315
+ this.createDataChannels();
316
+ this.addMediaSections(initialMediaSectionsAudio, initialMediaSectionsVideo);
317
+ }
318
+ const offer = await this.pcManager?.publisher.createInitialOffer();
319
+ if (offer) {
320
+ offerProto = toProtoSessionDescription(offer.offer, offer.offerId);
321
+ }
322
+ }
323
+ if (abortSignal?.aborted) {
324
+ throw ConnectionError.cancelled('Connection aborted');
325
+ }
326
+ const joinResponse = await this.client.join(
327
+ url,
328
+ token,
329
+ opts,
330
+ abortSignal,
331
+ useV0Path,
332
+ offerProto,
333
+ );
281
334
  this._isClosed = false;
282
335
  this.latestJoinResponse = joinResponse;
336
+ this.participantSid = joinResponse.participant?.sid;
283
337
 
284
338
  this.subscriberPrimary = joinResponse.subscriberPrimary;
285
- if (!this.pcManager) {
286
- await this.configure(joinResponse, !useV0Path);
287
- }
288
-
289
- // create offer
290
- if (!this.subscriberPrimary || joinResponse.fastPublish) {
291
- this.negotiate().catch((err) => {
292
- log.error(err, this.logContext);
293
- });
339
+ if (!useV0Path && isCompressionStreamSupported()) {
340
+ this.pcManager?.updateConfiguration(this.makeRTCConfiguration(joinResponse));
341
+ } else {
342
+ if (!this.pcManager) {
343
+ await this.configure(joinResponse, !useV0Path);
344
+ }
345
+ // create offer
346
+ if (!this.subscriberPrimary || joinResponse.fastPublish) {
347
+ this.negotiate().catch((err) => {
348
+ log.error(err, this.logContext);
349
+ });
350
+ }
294
351
  }
295
352
 
296
353
  this.registerOnLineListener();
@@ -355,11 +412,15 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
355
412
  dcCleanup(this.lossyDCSub);
356
413
  dcCleanup(this.reliableDC);
357
414
  dcCleanup(this.reliableDCSub);
415
+ dcCleanup(this.dataTrackDC);
416
+ dcCleanup(this.dataTrackDCSub);
358
417
 
359
418
  this.lossyDC = undefined;
360
419
  this.lossyDCSub = undefined;
361
420
  this.reliableDC = undefined;
362
421
  this.reliableDCSub = undefined;
422
+ this.dataTrackDC = undefined;
423
+ this.dataTrackDCSub = undefined;
363
424
  this.reliableMessageBuffer = new DataPacketBuffer();
364
425
  this.reliableDataSequence = 1;
365
426
  this.reliableReceivedState.clear();
@@ -445,25 +506,28 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
445
506
  this.regionUrlProvider = provider;
446
507
  }
447
508
 
448
- private async configure(joinResponse: JoinResponse, useSinglePeerConnection: boolean) {
509
+ private async configure(joinResponse?: JoinResponse, useSinglePeerConnection?: boolean) {
449
510
  // already configured
450
511
  if (this.pcManager && this.pcManager.currentState !== PCTransportState.NEW) {
451
512
  return;
452
513
  }
453
514
 
454
- this.participantSid = joinResponse.participant?.sid;
455
-
456
- const rtcConfig = this.makeRTCConfiguration(joinResponse);
457
-
458
- this.pcManager = new PCTransportManager(
459
- rtcConfig,
460
- useSinglePeerConnection
461
- ? 'publisher-only'
462
- : joinResponse.subscriberPrimary
463
- ? 'subscriber-primary'
464
- : 'publisher-primary',
465
- this.loggerOptions,
466
- );
515
+ if (!joinResponse) {
516
+ const rtcConfig = this.makeRTCConfiguration();
517
+ this.pcManager = new PCTransportManager('publisher-only', this.loggerOptions, rtcConfig);
518
+ } else {
519
+ this.participantSid = joinResponse.participant?.sid;
520
+ const rtcConfig = this.makeRTCConfiguration(joinResponse);
521
+ this.pcManager = new PCTransportManager(
522
+ useSinglePeerConnection
523
+ ? 'publisher-only'
524
+ : joinResponse.subscriberPrimary
525
+ ? 'subscriber-primary'
526
+ : 'publisher-primary',
527
+ this.loggerOptions,
528
+ rtcConfig,
529
+ );
530
+ }
467
531
 
468
532
  this.emit(EngineEvent.TransportsCreated, this.pcManager.publisher, this.pcManager.subscriber);
469
533
 
@@ -487,7 +551,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
487
551
  const shouldEmit = this.pcState === PCState.New;
488
552
  this.pcState = PCState.Connected;
489
553
  if (shouldEmit) {
490
- this.emit(EngineEvent.Connected, joinResponse);
554
+ this.emit(EngineEvent.Connected, this.latestJoinResponse!);
491
555
  }
492
556
  } else if (connectionState === PCTransportState.FAILED) {
493
557
  // on Safari, PeerConnection will switch to 'disconnected' during renegotiation
@@ -522,10 +586,6 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
522
586
  if (ev.streams.length === 0) return;
523
587
  this.emit(EngineEvent.MediaTrackAdded, ev.track, ev.streams[0], ev.receiver);
524
588
  };
525
-
526
- if (!supportOptionalDatachannel(joinResponse.serverInfo?.protocol)) {
527
- this.createDataChannels();
528
- }
529
589
  }
530
590
 
531
591
  private setupSignalClientCallbacks() {
@@ -614,17 +674,22 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
614
674
  };
615
675
 
616
676
  this.client.onMediaSectionsRequirement = (requirement: MediaSectionsRequirement) => {
617
- const transceiverInit: RTCRtpTransceiverInit = { direction: 'recvonly' };
618
- for (let i: number = 0; i < requirement.numAudios; i++) {
619
- this.pcManager?.addPublisherTransceiverOfKind('audio', transceiverInit);
620
- }
621
- for (let i: number = 0; i < requirement.numVideos; i++) {
622
- this.pcManager?.addPublisherTransceiverOfKind('video', transceiverInit);
623
- }
624
-
677
+ this.addMediaSections(requirement.numAudios, requirement.numVideos);
625
678
  this.negotiate();
626
679
  };
627
680
 
681
+ this.client.onPublishDataTrackResponse = (event: PublishDataTrackResponse) => {
682
+ this.emit(EngineEvent.PublishDataTrackResponse, event);
683
+ };
684
+
685
+ this.client.onUnPublishDataTrackResponse = (event: UnpublishDataTrackResponse) => {
686
+ this.emit(EngineEvent.UnPublishDataTrackResponse, event);
687
+ };
688
+
689
+ this.client.onDataTrackSubscriberHandles = (event: DataTrackSubscriberHandles) => {
690
+ this.emit(EngineEvent.DataTrackSubscriberHandles, event);
691
+ };
692
+
628
693
  this.client.onClose = () => {
629
694
  this.handleDisconnect('signal', ReconnectReason.RR_SIGNAL_DISCONNECTED);
630
695
  };
@@ -658,7 +723,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
658
723
  };
659
724
  }
660
725
 
661
- private makeRTCConfiguration(serverResponse: JoinResponse | ReconnectResponse): RTCConfiguration {
726
+ private makeRTCConfiguration(
727
+ serverResponse?: JoinResponse | ReconnectResponse,
728
+ ): RTCConfiguration {
662
729
  const rtcConfig = { ...this.rtcConfig };
663
730
 
664
731
  if (this.signalOpts?.e2eeEnabled) {
@@ -668,6 +735,15 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
668
735
  rtcConfig.encodedInsertableStreams = true;
669
736
  }
670
737
 
738
+ // @ts-ignore
739
+ rtcConfig.sdpSemantics = 'unified-plan';
740
+ // @ts-ignore
741
+ rtcConfig.continualGatheringPolicy = 'gather_continually';
742
+
743
+ if (!serverResponse) {
744
+ return rtcConfig;
745
+ }
746
+
671
747
  // update ICE servers before creating PeerConnection
672
748
  if (serverResponse.iceServers && !rtcConfig.iceServers) {
673
749
  const rtcIceServers: RTCIceServer[] = [];
@@ -691,14 +767,19 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
691
767
  rtcConfig.iceTransportPolicy = 'relay';
692
768
  }
693
769
 
694
- // @ts-ignore
695
- rtcConfig.sdpSemantics = 'unified-plan';
696
- // @ts-ignore
697
- rtcConfig.continualGatheringPolicy = 'gather_continually';
698
-
699
770
  return rtcConfig;
700
771
  }
701
772
 
773
+ private addMediaSections(numAudios: number, numVideos: number) {
774
+ const transceiverInit: RTCRtpTransceiverInit = { direction: 'recvonly' };
775
+ for (let i: number = 0; i < numAudios; i++) {
776
+ this.pcManager?.addPublisherTransceiverOfKind('audio', transceiverInit);
777
+ }
778
+ for (let i: number = 0; i < numVideos; i++) {
779
+ this.pcManager?.addPublisherTransceiverOfKind('video', transceiverInit);
780
+ }
781
+ }
782
+
702
783
  private createDataChannels() {
703
784
  if (!this.pcManager) {
704
785
  return;
@@ -713,6 +794,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
713
794
  this.reliableDC.onmessage = null;
714
795
  this.reliableDC.onerror = null;
715
796
  }
797
+ if (this.dataTrackDC) {
798
+ this.dataTrackDC.onmessage = null;
799
+ this.dataTrackDC.onerror = null;
800
+ }
716
801
 
717
802
  // create data channels
718
803
  this.lossyDC = this.pcManager.createPublisherDataChannel(lossyDataChannel, {
@@ -722,29 +807,39 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
722
807
  this.reliableDC = this.pcManager.createPublisherDataChannel(reliableDataChannel, {
723
808
  ordered: true,
724
809
  });
810
+ this.dataTrackDC = this.pcManager.createPublisherDataChannel(dataTrackDataChannel, {
811
+ ordered: false,
812
+ maxRetransmits: 0,
813
+ });
725
814
 
726
815
  // also handle messages over the pub channel, for backwards compatibility
727
816
  this.lossyDC.onmessage = this.handleDataMessage;
728
817
  this.reliableDC.onmessage = this.handleDataMessage;
818
+ this.dataTrackDC.onmessage = this.handleDataTrackMessage;
729
819
 
730
820
  // handle datachannel errors
731
821
  this.lossyDC.onerror = this.handleDataError;
732
822
  this.reliableDC.onerror = this.handleDataError;
823
+ this.dataTrackDC.onerror = this.handleDataError;
733
824
 
734
825
  // set up dc buffer threshold, set to 64kB (otherwise 0 by default)
735
826
  this.lossyDC.bufferedAmountLowThreshold = 65535;
736
827
  this.reliableDC.bufferedAmountLowThreshold = 65535;
828
+ this.dataTrackDC.bufferedAmountLowThreshold = 65535;
737
829
 
738
830
  // handle buffer amount low events
739
- this.lossyDC.onbufferedamountlow = this.handleBufferedAmountLow;
740
- this.reliableDC.onbufferedamountlow = this.handleBufferedAmountLow;
831
+ this.lossyDC.onbufferedamountlow = () => this.handleBufferedAmountLow(DataChannelKind.LOSSY);
832
+ this.reliableDC.onbufferedamountlow = () =>
833
+ this.handleBufferedAmountLow(DataChannelKind.RELIABLE);
834
+ this.dataTrackDC.onbufferedamountlow = () =>
835
+ this.handleBufferedAmountLow(DataChannelKind.DATA_TRACK_LOSSY);
741
836
 
742
837
  this.cleanupLossyDataStats();
743
838
  this.lossyDataStatInterval = setInterval(() => {
744
839
  this.lossyDataStatByterate = this.lossyDataStatCurrentBytes;
745
840
  this.lossyDataStatCurrentBytes = 0;
746
841
 
747
- const dc = this.dataChannelForKind(DataPacket_Kind.LOSSY);
842
+ const dc = this.dataChannelForKind(DataChannelKind.LOSSY);
748
843
  if (dc) {
749
844
  // control buffered latency to ~100ms
750
845
  const threshold = this.lossyDataStatByterate / 10;
@@ -760,15 +855,21 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
760
855
  if (!channel) {
761
856
  return;
762
857
  }
858
+ let handler;
763
859
  if (channel.label === reliableDataChannel) {
764
860
  this.reliableDCSub = channel;
861
+ handler = this.handleDataMessage;
765
862
  } else if (channel.label === lossyDataChannel) {
766
863
  this.lossyDCSub = channel;
864
+ handler = this.handleDataMessage;
865
+ } else if (channel.label === dataTrackDataChannel) {
866
+ this.dataTrackDCSub = channel;
867
+ handler = this.handleDataTrackMessage;
767
868
  } else {
768
869
  return;
769
870
  }
770
871
  this.log.debug(`on data channel ${channel.id}, ${channel.label}`, this.logContext);
771
- channel.onmessage = this.handleDataMessage;
872
+ channel.onmessage = handler;
772
873
  };
773
874
 
774
875
  private handleDataMessage = async (message: MessageEvent) => {
@@ -833,6 +934,21 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
833
934
  }
834
935
  };
835
936
 
937
+ private handleDataTrackMessage = async (message: MessageEvent) => {
938
+ // Decode / normalize into a common format
939
+ let buffer: ArrayBuffer | undefined;
940
+ if (message.data instanceof ArrayBuffer) {
941
+ buffer = message.data;
942
+ } else if (message.data instanceof Blob) {
943
+ buffer = await message.data.arrayBuffer();
944
+ } else {
945
+ this.log.error('unsupported data type', { ...this.logContext, data: message.data });
946
+ return;
947
+ }
948
+
949
+ this.emit('dataTrackPacketReceived', new Uint8Array(buffer));
950
+ };
951
+
836
952
  private handleDataError = (event: Event) => {
837
953
  const channel = event.currentTarget as RTCDataChannel;
838
954
  const channelKind = channel.maxRetransmits === 0 ? 'lossy' : 'reliable';
@@ -848,11 +964,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
848
964
  }
849
965
  };
850
966
 
851
- private handleBufferedAmountLow = (event: Event) => {
852
- const channel = event.currentTarget as RTCDataChannel;
853
- const channelKind =
854
- channel.maxRetransmits === 0 ? DataPacket_Kind.LOSSY : DataPacket_Kind.RELIABLE;
855
-
967
+ private handleBufferedAmountLow = (channelKind: DataChannelKind) => {
856
968
  this.updateAndEmitDCBufferStatus(channelKind);
857
969
  };
858
970
 
@@ -1281,7 +1393,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1281
1393
  },
1282
1394
  });
1283
1395
 
1284
- await this.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
1396
+ await this.sendDataPacket(packet, DataChannelKind.RELIABLE);
1285
1397
  }
1286
1398
 
1287
1399
  /** @internal */
@@ -1296,11 +1408,11 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1296
1408
  }),
1297
1409
  },
1298
1410
  });
1299
- await this.sendDataPacket(packet, DataPacket_Kind.RELIABLE);
1411
+ await this.sendDataPacket(packet, DataChannelKind.RELIABLE);
1300
1412
  }
1301
1413
 
1302
1414
  /* @internal */
1303
- async sendDataPacket(packet: DataPacket, kind: DataPacket_Kind) {
1415
+ async sendDataPacket(packet: DataPacket, kind: DataChannelKind) {
1304
1416
  // make sure we do have a data connection
1305
1417
  await this.ensurePublisherConnected(kind);
1306
1418
 
@@ -1319,57 +1431,93 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1319
1431
  }
1320
1432
  }
1321
1433
 
1322
- if (kind === DataPacket_Kind.RELIABLE) {
1434
+ if (kind === DataChannelKind.RELIABLE) {
1323
1435
  packet.sequence = this.reliableDataSequence;
1324
1436
  this.reliableDataSequence += 1;
1325
1437
  }
1326
1438
 
1327
1439
  const msg = packet.toBinary();
1328
1440
 
1441
+ switch (kind) {
1442
+ case DataChannelKind.LOSSY:
1443
+ case DataChannelKind.DATA_TRACK_LOSSY:
1444
+ return this.sendLossyBytes(msg, kind);
1445
+
1446
+ case DataChannelKind.RELIABLE:
1447
+ const dc = this.dataChannelForKind(kind);
1448
+ if (dc) {
1449
+ await this.waitForBufferStatusLow(kind);
1450
+ this.reliableMessageBuffer.push({ data: msg, sequence: packet.sequence });
1451
+
1452
+ if (this.attemptingReconnect) {
1453
+ return;
1454
+ }
1455
+
1456
+ dc.send(msg);
1457
+ }
1458
+
1459
+ this.updateAndEmitDCBufferStatus(kind);
1460
+ break;
1461
+ }
1462
+ }
1463
+
1464
+ /* @internal */
1465
+ async sendLossyBytes(
1466
+ bytes: Uint8Array,
1467
+ kind: Exclude<DataChannelKind, DataChannelKind.RELIABLE>,
1468
+ bufferStatusLowBehavior: 'drop' | 'wait' = 'drop',
1469
+ ) {
1470
+ // make sure we do have a data connection
1471
+ await this.ensurePublisherConnected(kind);
1472
+
1329
1473
  const dc = this.dataChannelForKind(kind);
1330
1474
  if (dc) {
1331
- if (kind === DataPacket_Kind.RELIABLE) {
1332
- await this.waitForBufferStatusLow(kind);
1333
- this.reliableMessageBuffer.push({ data: msg, sequence: packet.sequence });
1334
- } else {
1335
- // lossy channel, drop messages to reduce latency
1336
- if (!this.isBufferStatusLow(kind)) {
1337
- this.lossyDataDropCount += 1;
1338
- if (this.lossyDataDropCount % 100 === 0) {
1339
- this.log.warn(
1340
- `dropping lossy data channel messages, total dropped: ${this.lossyDataDropCount}`,
1341
- this.logContext,
1342
- );
1343
- }
1344
- return;
1475
+ if (!this.isBufferStatusLow(kind)) {
1476
+ // Depending on the exact circumstance that data is being sent, either drop or wait for the
1477
+ // buffer status to not be low before continuing.
1478
+ switch (bufferStatusLowBehavior) {
1479
+ case 'wait':
1480
+ await this.waitForBufferStatusLow(kind);
1481
+ break;
1482
+ case 'drop':
1483
+ // this.log.warn(`dropping lossy data channel message`, this.logContext);
1484
+ // Drop messages to reduce latency
1485
+ this.lossyDataDropCount += 1;
1486
+ if (this.lossyDataDropCount % 100 === 0) {
1487
+ this.log.warn(
1488
+ `dropping lossy data channel messages, total dropped: ${this.lossyDataDropCount}`,
1489
+ this.logContext,
1490
+ );
1491
+ }
1492
+ return;
1345
1493
  }
1346
- this.lossyDataStatCurrentBytes += msg.byteLength;
1347
1494
  }
1495
+ this.lossyDataStatCurrentBytes += bytes.byteLength;
1348
1496
 
1349
1497
  if (this.attemptingReconnect) {
1350
1498
  return;
1351
1499
  }
1352
1500
 
1353
- dc.send(msg);
1501
+ dc.send(bytes);
1354
1502
  }
1355
1503
 
1356
1504
  this.updateAndEmitDCBufferStatus(kind);
1357
1505
  }
1358
1506
 
1359
1507
  private async resendReliableMessagesForResume(lastMessageSeq: number) {
1360
- await this.ensurePublisherConnected(DataPacket_Kind.RELIABLE);
1361
- const dc = this.dataChannelForKind(DataPacket_Kind.RELIABLE);
1508
+ await this.ensurePublisherConnected(DataChannelKind.RELIABLE);
1509
+ const dc = this.dataChannelForKind(DataChannelKind.RELIABLE);
1362
1510
  if (dc) {
1363
1511
  this.reliableMessageBuffer.popToSequence(lastMessageSeq);
1364
1512
  this.reliableMessageBuffer.getAll().forEach((msg) => {
1365
1513
  dc.send(msg.data);
1366
1514
  });
1367
1515
  }
1368
- this.updateAndEmitDCBufferStatus(DataPacket_Kind.RELIABLE);
1516
+ this.updateAndEmitDCBufferStatus(DataChannelKind.RELIABLE);
1369
1517
  }
1370
1518
 
1371
- private updateAndEmitDCBufferStatus = (kind: DataPacket_Kind) => {
1372
- if (kind === DataPacket_Kind.RELIABLE) {
1519
+ private updateAndEmitDCBufferStatus = (kind: DataChannelKind) => {
1520
+ if (kind === DataChannelKind.RELIABLE) {
1373
1521
  const dc = this.dataChannelForKind(kind);
1374
1522
  if (dc) {
1375
1523
  this.reliableMessageBuffer.alignBufferedAmount(dc.bufferedAmount);
@@ -1383,14 +1531,14 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1383
1531
  }
1384
1532
  };
1385
1533
 
1386
- private isBufferStatusLow = (kind: DataPacket_Kind): boolean | undefined => {
1534
+ private isBufferStatusLow = (kind: DataChannelKind): boolean | undefined => {
1387
1535
  const dc = this.dataChannelForKind(kind);
1388
1536
  if (dc) {
1389
1537
  return dc.bufferedAmount <= dc.bufferedAmountLowThreshold;
1390
1538
  }
1391
1539
  };
1392
1540
 
1393
- waitForBufferStatusLow(kind: DataPacket_Kind): TypedPromise<void, UnexpectedConnectionState> {
1541
+ waitForBufferStatusLow(kind: DataChannelKind): TypedPromise<void, UnexpectedConnectionState> {
1394
1542
  return new TypedPromise(async (resolve, reject) => {
1395
1543
  if (this.isBufferStatusLow(kind)) {
1396
1544
  resolve();
@@ -1410,7 +1558,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1410
1558
  * @internal
1411
1559
  */
1412
1560
  async ensureDataTransportConnected(
1413
- kind: DataPacket_Kind,
1561
+ kind: DataChannelKind,
1414
1562
  subscriber: boolean = this.subscriberPrimary,
1415
1563
  ) {
1416
1564
  if (!this.pcManager) {
@@ -1465,7 +1613,7 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1465
1613
  );
1466
1614
  }
1467
1615
 
1468
- private async ensurePublisherConnected(kind: DataPacket_Kind) {
1616
+ private async ensurePublisherConnected(kind: DataChannelKind) {
1469
1617
  if (!this.publisherConnectionPromise) {
1470
1618
  this.publisherConnectionPromise = this.ensureDataTransportConnected(kind, false);
1471
1619
  }
@@ -1506,7 +1654,8 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1506
1654
  if (
1507
1655
  this.pcManager.publisher.getTransceivers().length == 0 &&
1508
1656
  !this.lossyDC &&
1509
- !this.reliableDC
1657
+ !this.reliableDC &&
1658
+ !this.dataTrackDC
1510
1659
  ) {
1511
1660
  this.createDataChannels();
1512
1661
  }
@@ -1566,26 +1715,35 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1566
1715
  });
1567
1716
  }
1568
1717
 
1569
- dataChannelForKind(kind: DataPacket_Kind, sub?: boolean): RTCDataChannel | undefined {
1570
- if (!sub) {
1571
- if (kind === DataPacket_Kind.LOSSY) {
1572
- return this.lossyDC;
1573
- }
1574
- if (kind === DataPacket_Kind.RELIABLE) {
1575
- return this.reliableDC;
1576
- }
1577
- } else {
1578
- if (kind === DataPacket_Kind.LOSSY) {
1579
- return this.lossyDCSub;
1580
- }
1581
- if (kind === DataPacket_Kind.RELIABLE) {
1582
- return this.reliableDCSub;
1583
- }
1718
+ dataChannelForKind(kind: DataChannelKind, sub?: boolean): RTCDataChannel | undefined {
1719
+ switch (kind) {
1720
+ case DataChannelKind.RELIABLE:
1721
+ if (!sub) {
1722
+ return this.reliableDC;
1723
+ } else {
1724
+ return this.reliableDCSub;
1725
+ }
1726
+ case DataChannelKind.LOSSY:
1727
+ if (!sub) {
1728
+ return this.lossyDC;
1729
+ } else {
1730
+ return this.lossyDCSub;
1731
+ }
1732
+ case DataChannelKind.DATA_TRACK_LOSSY:
1733
+ if (!sub) {
1734
+ return this.dataTrackDC;
1735
+ } else {
1736
+ return this.dataTrackDCSub;
1737
+ }
1584
1738
  }
1585
1739
  }
1586
1740
 
1587
1741
  /** @internal */
1588
- sendSyncState(remoteTracks: RemoteTrackPublication[], localTracks: LocalTrackPublication[]) {
1742
+ sendSyncState(
1743
+ remoteTracks: RemoteTrackPublication[],
1744
+ localTracks: LocalTrackPublication[],
1745
+ localDataTrackInfos: Array<DataTrackInfo>,
1746
+ ) {
1589
1747
  if (!this.pcManager) {
1590
1748
  this.log.warn('sync state cannot be sent without peer connection setup', this.logContext);
1591
1749
  return;
@@ -1657,6 +1815,9 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1657
1815
  lastSeq: seq,
1658
1816
  });
1659
1817
  }),
1818
+ publishDataTracks: localDataTrackInfos.map((info) => {
1819
+ return new PublishDataTrackResponse({ info: DataTrackInfo.toProtobuf(info) });
1820
+ }),
1660
1821
  }),
1661
1822
  );
1662
1823
  }
@@ -1680,10 +1841,10 @@ export default class RTCEngine extends (EventEmitter as new () => TypedEventEmit
1680
1841
  );
1681
1842
  }
1682
1843
  };
1683
- getInfo(this.dataChannelForKind(DataPacket_Kind.LOSSY), SignalTarget.PUBLISHER);
1684
- getInfo(this.dataChannelForKind(DataPacket_Kind.RELIABLE), SignalTarget.PUBLISHER);
1685
- getInfo(this.dataChannelForKind(DataPacket_Kind.LOSSY, true), SignalTarget.SUBSCRIBER);
1686
- getInfo(this.dataChannelForKind(DataPacket_Kind.RELIABLE, true), SignalTarget.SUBSCRIBER);
1844
+ getInfo(this.dataChannelForKind(DataChannelKind.LOSSY), SignalTarget.PUBLISHER);
1845
+ getInfo(this.dataChannelForKind(DataChannelKind.RELIABLE), SignalTarget.PUBLISHER);
1846
+ getInfo(this.dataChannelForKind(DataChannelKind.LOSSY, true), SignalTarget.SUBSCRIBER);
1847
+ getInfo(this.dataChannelForKind(DataChannelKind.RELIABLE, true), SignalTarget.SUBSCRIBER);
1687
1848
  return infos;
1688
1849
  }
1689
1850
 
@@ -1790,7 +1951,7 @@ export type EngineEventCallbacks = {
1790
1951
  /** @internal */
1791
1952
  trackSenderAdded: (track: Track, sender: RTCRtpSender) => void;
1792
1953
  rtpVideoMapUpdate: (rtpMap: Map<number, VideoCodec>) => void;
1793
- dcBufferStatusChanged: (isLow: boolean, kind: DataPacket_Kind) => void;
1954
+ dcBufferStatusChanged: (isLow: boolean, kind: DataChannelKind) => void;
1794
1955
  participantUpdate: (infos: ParticipantInfo[]) => void;
1795
1956
  roomUpdate: (room: RoomModel) => void;
1796
1957
  roomMoved: (room: RoomMovedResponse) => void;
@@ -1806,12 +1967,13 @@ export type EngineEventCallbacks = {
1806
1967
  offline: () => void;
1807
1968
  signalRequestResponse: (response: RequestResponse) => void;
1808
1969
  signalConnected: (joinResp: JoinResponse) => void;
1970
+ publishDataTrackResponse: (event: PublishDataTrackResponse) => void;
1971
+ unPublishDataTrackResponse: (event: UnpublishDataTrackResponse) => void;
1972
+ dataTrackSubscriberHandles: (event: DataTrackSubscriberHandles) => void;
1973
+ dataTrackPacketReceived: (packet: Uint8Array) => void;
1974
+ joined: (joinResponse: JoinResponse) => void;
1809
1975
  };
1810
1976
 
1811
- function supportOptionalDatachannel(protocol: number | undefined): boolean {
1812
- return protocol !== undefined && protocol > 13;
1813
- }
1814
-
1815
1977
  function applyUserDataCompat(newObj: DataPacket, oldObj: UserPacket) {
1816
1978
  const participantIdentity = newObj.participantIdentity
1817
1979
  ? newObj.participantIdentity