@livedigital/client 3.3.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -231,6 +231,7 @@ export declare type CreateDataConsumerPayload = {
231
231
  producerId: string;
232
232
  appId?: string;
233
233
  channelId?: string;
234
+ ordered?: boolean;
234
235
  };
235
236
  export declare type CreateConsumerResponse = {
236
237
  consumer: Consumer;
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@livedigital/client",
3
3
  "author": "vlprojects",
4
4
  "license": "MIT",
5
- "version": "3.3.0",
5
+ "version": "3.4.0",
6
6
  "private": false,
7
7
  "bugs": {
8
8
  "url": "https://github.com/vlprojects/livedigital-sdk/issues"
@@ -1,5 +1,7 @@
1
1
  import { LogLevel } from '../types/common';
2
2
 
3
+ export const SIGNALING_API_VERSION = 2;
4
+
3
5
  export const LOG_LEVEL_ERROR: LogLevel = 3;
4
6
  export const LOG_LEVEL_WARN: LogLevel = 4;
5
7
  export const LOG_LEVEL_INFO: LogLevel = 6;
@@ -9,6 +9,7 @@ export const CHANNEL_EVENTS = {
9
9
  activityConfirmationRequired: 'channel.activityConfirmationRequired',
10
10
  activityConfirmationExpired: 'channel.activityConfirmationExpired',
11
11
  getAudioObserverProducer: 'channel.getAudioObserverProducer',
12
+ getGeneralDataProducer: 'channel.getGeneralDataProducer',
12
13
  };
13
14
 
14
15
  export const CLIENT_EVENTS = {
@@ -24,6 +24,24 @@ class ChannelEventHandler {
24
24
  });
25
25
  }
26
26
 
27
+ handleDataChannelEvent(payload: string): void {
28
+ try {
29
+ const { event, data } = JSON.parse(payload) as { event: string; data: Record<string, unknown> };
30
+ this.doHandleDataChannelEvent(event, data);
31
+ } catch (error: unknown) {
32
+ this.logger.error('Failed to handle data channel event', {
33
+ error,
34
+ payload,
35
+ });
36
+ }
37
+ }
38
+
39
+ private doHandleDataChannelEvent(event: string, payload: Record<string, unknown>) {
40
+ if (event === CHANNEL_EVENTS.updatePeerAppData) {
41
+ this.handlePeerAppDataUpdate(payload as UpdatePeerAppDataPayload);
42
+ }
43
+ }
44
+
27
45
  public subscribeToEvents(): void {
28
46
  const { connection } = this.engine.network.socket;
29
47
  if (!connection) {
@@ -62,15 +80,6 @@ class ChannelEventHandler {
62
80
  this.engine.clientEventEmitter.safeEmit(CLIENT_EVENTS.activityConfirmationAcquired, event);
63
81
  this.logger.info('Notify the channel that the activity has been acquired.', event);
64
82
  });
65
-
66
- connection.on(CHANNEL_EVENTS.updatePeerAppData, ({ peerId, appData }: UpdatePeerAppDataPayload) => {
67
- const peer = this.engine.peers.find((item) => item.id === peerId);
68
- if (!peer) {
69
- return;
70
- }
71
-
72
- peer.observer.emit(CHANNEL_EVENTS.updatePeerAppData, appData);
73
- });
74
83
  }
75
84
 
76
85
  private removeEventListeners() {
@@ -93,6 +102,16 @@ class ChannelEventHandler {
93
102
  eventNames.forEach((x) => connection.removeAllListeners(x));
94
103
  }
95
104
 
105
+ private handlePeerAppDataUpdate({ peerId, appData }: UpdatePeerAppDataPayload) {
106
+ const peer = this.engine.peers.find(({ id }) => id === peerId);
107
+
108
+ if (!peer) {
109
+ return;
110
+ }
111
+
112
+ peer.observer.emit(CHANNEL_EVENTS.updatePeerAppData, appData);
113
+ }
114
+
96
115
  public reset() {
97
116
  this.removeEventListeners();
98
117
  }
@@ -100,11 +100,15 @@ class Engine {
100
100
 
101
101
  private audioObserver?: DataConsumer;
102
102
 
103
+ private generalDataConsumer?: DataConsumer;
104
+
103
105
  private activeSpeakerPeer?: Peer;
104
106
 
105
107
  private rejoinRequested = false;
106
108
 
107
- private channelAudioObserverEventHandle: (data: string) => void;
109
+ private readonly handleChannelAudioObserverEvent: (data: string) => void;
110
+
111
+ private readonly handleDataChannelEvent: (data: string) => void;
108
112
 
109
113
  constructor(params: EngineParams) {
110
114
  const {
@@ -147,10 +151,14 @@ class Engine {
147
151
  onLogMessage: params.onLogMessage,
148
152
  });
149
153
 
150
- this.channelAudioObserverEventHandle = (data) => {
154
+ this.handleChannelAudioObserverEvent = (data) => {
151
155
  this.channelAudioObserverEventHandler.handle(data);
152
156
  };
153
157
 
158
+ this.handleDataChannelEvent = (data) => {
159
+ this.channelEventsHandler.handleDataChannelEvent(data);
160
+ };
161
+
154
162
  this.logger = new Logger({
155
163
  logLevel: this.logLevel,
156
164
  namespace: 'Engine',
@@ -220,9 +228,12 @@ class Engine {
220
228
  await this.network.closeReceiveTransport();
221
229
  await this.media.clearTracks();
222
230
 
223
- this.audioObserver?.removeListener('message', this.channelAudioObserverEventHandle);
231
+ this.audioObserver?.removeListener('message', this.handleChannelAudioObserverEvent);
224
232
  this.audioObserver?.close();
225
233
 
234
+ this.generalDataConsumer?.removeListener('message', this.handleDataChannelEvent);
235
+ this.generalDataConsumer?.close();
236
+
226
237
  this.channelEventsHandler.reset();
227
238
  this.mediaSoupEventsHandler.reset();
228
239
 
@@ -594,7 +605,10 @@ class Engine {
594
605
  this.mediaSoupEventsHandler.subscribeToEvents();
595
606
  this.isJoined = true;
596
607
  this.logger.debug('Successfully joined channel', { channelId });
597
- await this.createAudioObserver();
608
+ await Promise.all([
609
+ this.createAudioObserver(),
610
+ this.createGeneralDataConsumer(),
611
+ ]);
598
612
  } catch (error) {
599
613
  this.logger.error('performJoin()', { error });
600
614
  throw error;
@@ -695,7 +709,7 @@ class Engine {
695
709
  channelId: this.channelId,
696
710
  });
697
711
 
698
- audioObserver.on('message', this.channelAudioObserverEventHandle);
712
+ audioObserver.on('message', this.handleChannelAudioObserverEvent);
699
713
 
700
714
  this.audioObserver = audioObserver;
701
715
  this.logger.debug('Successfully create audio observer', logCtx);
@@ -704,6 +718,39 @@ class Engine {
704
718
  }
705
719
  }
706
720
 
721
+ private async createGeneralDataConsumer(): Promise<void> {
722
+ if (!this.isJoined) {
723
+ throw new NeedJoinFirstError('Need to join first');
724
+ }
725
+
726
+ const logCtx = {
727
+ channelId: this.channelId,
728
+ appId: this.appId,
729
+ peerId: this.myPeer?.id,
730
+ };
731
+
732
+ try {
733
+ const { producerId } = await this.network.getGeneralDataProducer() as { producerId: string };
734
+ this.generalDataConsumer = await this.network.createDataConsumer({
735
+ producerId,
736
+ appId: this.appId,
737
+ channelId: this.channelId,
738
+ ordered: true,
739
+ });
740
+
741
+ this.generalDataConsumer.on('message', this.handleDataChannelEvent);
742
+ this.logger.debug('Successfully created general data consumer', {
743
+ ...logCtx,
744
+ producerId,
745
+ });
746
+ } catch (error) {
747
+ this.logger.error('Failed to create general data consumer', {
748
+ ...logCtx,
749
+ error,
750
+ });
751
+ }
752
+ }
753
+
707
754
  private triggerRejoinEventIfAppropriate(reason?: string): void {
708
755
  if (this.rejoinRequested && !this.isChannelJoining) {
709
756
  return;
@@ -3,6 +3,7 @@ import EnhancedEventEmitter from '../../EnhancedEventEmitter';
3
3
  import { SocketIOEvents } from '../../types/socket';
4
4
  import { LogLevel, LogMessageHandler, SocketResponse } from '../../types/common';
5
5
  import Logger from '../Logger';
6
+ import { SIGNALING_API_VERSION } from '../../constants/common';
6
7
 
7
8
  export type SocketIOConstructorParams = {
8
9
  logLevel: LogLevel,
@@ -57,6 +58,7 @@ class SocketIO {
57
58
  rememberUpgrade: false,
58
59
  auth: {
59
60
  token,
61
+ apiVersion: SIGNALING_API_VERSION,
60
62
  },
61
63
  });
62
64
 
@@ -392,6 +392,7 @@ class Network {
392
392
  producerId,
393
393
  appId,
394
394
  channelId,
395
+ ordered,
395
396
  }: CreateDataConsumerPayload): Promise<DataConsumer> {
396
397
  const transport = this.receiveTransport;
397
398
  if (!transport) {
@@ -401,6 +402,7 @@ class Network {
401
402
 
402
403
  this.logger.debug('createDataConsumer()', { producerId });
403
404
  const options = await this.socket.request(MEDIASOUP_EVENTS.createDataConsumer, {
405
+ ordered,
404
406
  dataProducerId: producerId,
405
407
  transportId: transport.id,
406
408
  appData: {
@@ -436,6 +438,10 @@ class Network {
436
438
  return this.socket.request(CHANNEL_EVENTS.getAudioObserverProducer);
437
439
  }
438
440
 
441
+ async getGeneralDataProducer(): Promise<SocketResponse> {
442
+ return this.socket.request(CHANNEL_EVENTS.getGeneralDataProducer);
443
+ }
444
+
439
445
  async getTransportsStateInfo(): Promise<TransportsStateInfo> {
440
446
  const [receive, send] = await Promise.all([
441
447
  this.getParsedTransportStats(this.receiveTransport),
@@ -286,9 +286,10 @@ export type CreateConsumerPayload = {
286
286
  };
287
287
 
288
288
  export type CreateDataConsumerPayload = {
289
- producerId: string,
290
- appId?: string,
291
- channelId?: string,
289
+ producerId: string;
290
+ appId?: string;
291
+ channelId?: string;
292
+ ordered?: boolean;
292
293
  };
293
294
 
294
295
  export type CreateConsumerResponse = {