@livedigital/client 3.1.0-disable-transport-disconnected-handler.4 → 3.1.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.
- package/dist/constants/common.ts +20 -0
- package/dist/constants/encodings.ts +26 -0
- package/dist/constants/events.d.ts +0 -8
- package/dist/constants/events.ts +83 -0
- package/dist/constants/videoConstrains.ts +10 -0
- package/dist/engine/Peer.d.ts +1 -0
- package/dist/engine/handlers/ChannelEventHandler.d.ts +2 -0
- package/dist/engine/handlers/MediaSoupEventHandler.d.ts +2 -0
- package/dist/engine/index.d.ts +2 -0
- package/dist/engine/network/index.d.ts +6 -3
- package/dist/index.es.js +3 -3
- package/dist/index.js +3 -3
- package/dist/types/network.d.ts +1 -1
- package/dist/types/socket.d.ts +13 -0
- package/package.json +3 -3
- package/src/constants/events.ts +0 -9
- package/src/engine/Peer.ts +23 -0
- package/src/engine/handlers/ChannelEventHandler.ts +24 -0
- package/src/engine/handlers/MediaSoupEventHandler.ts +31 -0
- package/src/engine/index.ts +49 -13
- package/src/engine/network/Socket.ts +17 -16
- package/src/engine/network/index.ts +66 -8
- package/src/types/media.ts +9 -9
- package/src/types/network.ts +1 -1
- package/src/types/socket.ts +16 -0
package/dist/types/network.d.ts
CHANGED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare enum SocketIOEvents {
|
|
2
|
+
Connect = "connect",
|
|
3
|
+
Connected = "connected",
|
|
4
|
+
ConnectError = "connect_error",
|
|
5
|
+
Reconnect = "reconnect",
|
|
6
|
+
Reconnecting = "reconnecting",
|
|
7
|
+
Reconnected = "reconnected",
|
|
8
|
+
ReconnectAttempt = "reconnect_attempt",
|
|
9
|
+
Disconnect = "disconnect",
|
|
10
|
+
Disconnected = "disconnected",
|
|
11
|
+
Error = "error",
|
|
12
|
+
State = "state"
|
|
13
|
+
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@livedigital/client",
|
|
3
3
|
"author": "vlprojects",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "3.1.0
|
|
5
|
+
"version": "3.1.0",
|
|
6
6
|
"private": false,
|
|
7
7
|
"bugs": {
|
|
8
8
|
"url": "https://github.com/vlprojects/livedigital-sdk/issues"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"url": "https://github.com/VLprojects/livedigital-sdk.git"
|
|
24
24
|
},
|
|
25
25
|
"scripts": {
|
|
26
|
-
"build": "rm -rf dist && rollup -c && tsc --importHelpers",
|
|
26
|
+
"build": "rm -rf dist && rollup -c && tsc --importHelpers && cp src/constants/* dist/constants/",
|
|
27
27
|
"lint": "eslint ./src",
|
|
28
28
|
"test": "NODE_ENV=test mocha --config test/utils/runners/mocha/.mocharc.js"
|
|
29
29
|
},
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"axios": "^0.21.4",
|
|
47
47
|
"bowser": "^2.11.0",
|
|
48
48
|
"debug": "^4.3.4",
|
|
49
|
-
"mediasoup-client": "^3.6.
|
|
49
|
+
"mediasoup-client": "^3.6.103",
|
|
50
50
|
"qs": "^6.11.0",
|
|
51
51
|
"serialize-error": "^7.0.1",
|
|
52
52
|
"socket.io-client": "^4.7.2",
|
package/src/constants/events.ts
CHANGED
|
@@ -53,15 +53,6 @@ export const PEER_EVENTS = {
|
|
|
53
53
|
appDataUpdated: 'app-data-updated',
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
-
export enum SocketIOEvents {
|
|
57
|
-
Connected = 'connected',
|
|
58
|
-
Reconnecting = 'reconnecting',
|
|
59
|
-
Reconnected = 'reconnected',
|
|
60
|
-
Disconnected = 'disconnected',
|
|
61
|
-
Reconnect = 'reconnect',
|
|
62
|
-
Error = 'error',
|
|
63
|
-
}
|
|
64
|
-
|
|
65
56
|
export const MEDIASOUP_EVENTS = {
|
|
66
57
|
newProducer: 'peer.newProducer',
|
|
67
58
|
producerClose: 'producer.close',
|
package/src/engine/Peer.ts
CHANGED
|
@@ -417,6 +417,29 @@ class Peer {
|
|
|
417
417
|
});
|
|
418
418
|
}
|
|
419
419
|
|
|
420
|
+
reset() {
|
|
421
|
+
this.producers.clear();
|
|
422
|
+
|
|
423
|
+
this.tracks.forEach((x) => x.close());
|
|
424
|
+
this.tracks.clear();
|
|
425
|
+
|
|
426
|
+
const eventNames = [
|
|
427
|
+
MEDIASOUP_EVENTS.newProducer,
|
|
428
|
+
MEDIASOUP_EVENTS.producerClose,
|
|
429
|
+
MEDIASOUP_EVENTS.closeConsumer,
|
|
430
|
+
MEDIASOUP_EVENTS.pauseConsumer,
|
|
431
|
+
MEDIASOUP_EVENTS.resumeConsumer,
|
|
432
|
+
MEDIASOUP_EVENTS.consumerScoreChanged,
|
|
433
|
+
MEDIASOUP_EVENTS.consumerScoreChanged,
|
|
434
|
+
MEDIASOUP_EVENTS.producerScoreChanged,
|
|
435
|
+
MEDIASOUP_EVENTS.consumerChangePreferredLayers,
|
|
436
|
+
MEDIASOUP_EVENTS.producerSetMaxSpatialLayer,
|
|
437
|
+
CHANNEL_EVENTS.updatePeerAppData,
|
|
438
|
+
];
|
|
439
|
+
|
|
440
|
+
eventNames.forEach((x) => this.observer.removeAllListeners(x));
|
|
441
|
+
}
|
|
442
|
+
|
|
420
443
|
private emitConnectionQuality(): void {
|
|
421
444
|
// after the initialization a new layer, or new producer, scores of producers and consumers drop for a short time
|
|
422
445
|
setTimeout(() => {
|
|
@@ -72,6 +72,30 @@ class ChannelEventHandler {
|
|
|
72
72
|
peer.observer.emit(CHANNEL_EVENTS.updatePeerAppData, appData);
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
|
+
|
|
76
|
+
private removeEventListeners() {
|
|
77
|
+
const { connection } = this.engine.network.socket;
|
|
78
|
+
|
|
79
|
+
if (!connection) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const eventNames = [
|
|
84
|
+
CHANNEL_EVENTS.channelEvent,
|
|
85
|
+
CHANNEL_EVENTS.channelJoin,
|
|
86
|
+
CHANNEL_EVENTS.channelLeave,
|
|
87
|
+
CHANNEL_EVENTS.activityConfirmationRequired,
|
|
88
|
+
CHANNEL_EVENTS.activityConfirmationExpired,
|
|
89
|
+
CHANNEL_EVENTS.activityConfirmationAcquired,
|
|
90
|
+
CHANNEL_EVENTS.updatePeerAppData,
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
eventNames.forEach((x) => connection.removeAllListeners(x));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
public reset() {
|
|
97
|
+
this.removeEventListeners();
|
|
98
|
+
}
|
|
75
99
|
}
|
|
76
100
|
|
|
77
101
|
export default ChannelEventHandler;
|
|
@@ -215,6 +215,37 @@ class MediaSoupEventHandler {
|
|
|
215
215
|
});
|
|
216
216
|
}
|
|
217
217
|
|
|
218
|
+
private removeEventListeners() {
|
|
219
|
+
const { connection } = this.engine.network.socket;
|
|
220
|
+
|
|
221
|
+
if (!connection) {
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const eventNames = [
|
|
226
|
+
MEDIASOUP_EVENTS.producerClose,
|
|
227
|
+
MEDIASOUP_EVENTS.newProducer,
|
|
228
|
+
MEDIASOUP_EVENTS.closeConsumer,
|
|
229
|
+
MEDIASOUP_EVENTS.resumeConsumer,
|
|
230
|
+
MEDIASOUP_EVENTS.pauseConsumer,
|
|
231
|
+
MEDIASOUP_EVENTS.consumerChangePreferredLayers,
|
|
232
|
+
MEDIASOUP_EVENTS.consumerScoreChanged,
|
|
233
|
+
MEDIASOUP_EVENTS.producerScoreChanged,
|
|
234
|
+
MEDIASOUP_EVENTS.producerRequestMaxSpatialLayer,
|
|
235
|
+
MEDIASOUP_EVENTS.producerSetMaxSpatialLayer,
|
|
236
|
+
MEDIASOUP_EVENTS.transportConnectionTimeout,
|
|
237
|
+
MEDIASOUP_EVENTS.producerPaused,
|
|
238
|
+
MEDIASOUP_EVENTS.producerResumed,
|
|
239
|
+
MEDIASOUP_EVENTS.producerForceClosed,
|
|
240
|
+
];
|
|
241
|
+
|
|
242
|
+
eventNames.forEach((x) => connection.removeAllListeners(x));
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
public reset() {
|
|
246
|
+
this.removeEventListeners();
|
|
247
|
+
}
|
|
248
|
+
|
|
218
249
|
private async handleProducerSetMaxSpatialLayer({
|
|
219
250
|
producerId,
|
|
220
251
|
spatialLayer,
|
package/src/engine/index.ts
CHANGED
|
@@ -24,8 +24,9 @@ import ChannelEventHandler from './handlers/ChannelEventHandler';
|
|
|
24
24
|
import MediaSoupEventHandler from './handlers/MediaSoupEventHandler';
|
|
25
25
|
import Logger from './Logger';
|
|
26
26
|
import {
|
|
27
|
-
CHANNEL_EVENTS, CLIENT_EVENTS, INTERNAL_CLIENT_EVENTS,
|
|
27
|
+
CHANNEL_EVENTS, CLIENT_EVENTS, INTERNAL_CLIENT_EVENTS,
|
|
28
28
|
} from '../constants/events';
|
|
29
|
+
import { SocketIOEvents } from '../types/socket';
|
|
29
30
|
import {
|
|
30
31
|
GetNodeRequest,
|
|
31
32
|
JoinChannelRequest,
|
|
@@ -103,6 +104,8 @@ class Engine {
|
|
|
103
104
|
|
|
104
105
|
private rejoinRequested = false;
|
|
105
106
|
|
|
107
|
+
private channelAudioObserverEventHandle: (data: string) => void;
|
|
108
|
+
|
|
106
109
|
constructor(params: EngineParams) {
|
|
107
110
|
const {
|
|
108
111
|
clientEventEmitter,
|
|
@@ -144,6 +147,10 @@ class Engine {
|
|
|
144
147
|
onLogMessage: params.onLogMessage,
|
|
145
148
|
});
|
|
146
149
|
|
|
150
|
+
this.channelAudioObserverEventHandle = (data) => {
|
|
151
|
+
this.channelAudioObserverEventHandler.handle(data);
|
|
152
|
+
};
|
|
153
|
+
|
|
147
154
|
this.logger = new Logger({
|
|
148
155
|
logLevel: this.logLevel,
|
|
149
156
|
namespace: 'Engine',
|
|
@@ -161,7 +168,6 @@ class Engine {
|
|
|
161
168
|
});
|
|
162
169
|
|
|
163
170
|
this.watchSocketState();
|
|
164
|
-
this.watchClientEvents();
|
|
165
171
|
}
|
|
166
172
|
|
|
167
173
|
private async initialize(): Promise<void> {
|
|
@@ -182,10 +188,13 @@ class Engine {
|
|
|
182
188
|
} catch (error: unknown) {
|
|
183
189
|
this.logger.error('initialize()', { error });
|
|
184
190
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
191
|
+
const isDeviceNotSupported = error instanceof MediasoupUnsupportedError
|
|
192
|
+
&& error.message === 'device not supported';
|
|
193
|
+
|
|
194
|
+
const isNoRTCPeerConnection = error instanceof Error
|
|
195
|
+
&& error.message === 'RTCPeerConnection is not defined';
|
|
196
|
+
|
|
197
|
+
if (isDeviceNotSupported || isNoRTCPeerConnection) {
|
|
189
198
|
throw new UnsupportedError('Device not supported', UnsupportedError.UNSUPPORTED_DEVICE_CODE);
|
|
190
199
|
}
|
|
191
200
|
|
|
@@ -200,13 +209,25 @@ class Engine {
|
|
|
200
209
|
this.app = undefined;
|
|
201
210
|
this.channel = undefined;
|
|
202
211
|
this.webRtcIssueDetector?.stopWatchingNewPeerConnections();
|
|
212
|
+
|
|
213
|
+
this.network.reset();
|
|
203
214
|
this.network.socket.disconnect();
|
|
215
|
+
|
|
216
|
+
this.peersRepository.forEach((x) => x.reset());
|
|
204
217
|
this.peersRepository.clear();
|
|
218
|
+
|
|
205
219
|
await this.network.closeSendTransport();
|
|
206
220
|
await this.network.closeReceiveTransport();
|
|
207
221
|
await this.media.clearTracks();
|
|
222
|
+
|
|
223
|
+
this.audioObserver?.removeListener('message', this.channelAudioObserverEventHandle);
|
|
208
224
|
this.audioObserver?.close();
|
|
209
225
|
|
|
226
|
+
this.channelEventsHandler.reset();
|
|
227
|
+
this.mediaSoupEventsHandler.reset();
|
|
228
|
+
|
|
229
|
+
this.removeClientEventEmitterListeners();
|
|
230
|
+
|
|
210
231
|
this.logger.debug('release()', {
|
|
211
232
|
socketId: this.mySocketId,
|
|
212
233
|
});
|
|
@@ -216,8 +237,21 @@ class Engine {
|
|
|
216
237
|
}
|
|
217
238
|
}
|
|
218
239
|
|
|
240
|
+
private removeClientEventEmitterListeners(): void {
|
|
241
|
+
const eventNames = [
|
|
242
|
+
INTERNAL_CLIENT_EVENTS.trackProduced,
|
|
243
|
+
INTERNAL_CLIENT_EVENTS.trackUnproduced,
|
|
244
|
+
INTERNAL_CLIENT_EVENTS.trackPaused,
|
|
245
|
+
INTERNAL_CLIENT_EVENTS.trackResumed,
|
|
246
|
+
INTERNAL_CLIENT_EVENTS.trackClosed,
|
|
247
|
+
INTERNAL_CLIENT_EVENTS.trackReopened,
|
|
248
|
+
];
|
|
249
|
+
|
|
250
|
+
eventNames.forEach((x) => this.clientEventEmitter.removeAllListeners(x));
|
|
251
|
+
}
|
|
252
|
+
|
|
219
253
|
private watchSocketState(): void {
|
|
220
|
-
this.network.socket.observer.on(
|
|
254
|
+
this.network.socket.observer.on(SocketIOEvents.State, (evt: SocketObserverEvent) => {
|
|
221
255
|
const { state, code, error } = evt;
|
|
222
256
|
this.clientEventEmitter.emit(state, { code, error });
|
|
223
257
|
|
|
@@ -274,6 +308,7 @@ class Engine {
|
|
|
274
308
|
try {
|
|
275
309
|
this.logger.debug('join()', { params });
|
|
276
310
|
this.isChannelJoining = true;
|
|
311
|
+
this.watchClientEvents();
|
|
277
312
|
await this.connectToSocketServerWithRetry(params);
|
|
278
313
|
await this.performJoin({ appData: params.appData });
|
|
279
314
|
} catch (error) {
|
|
@@ -316,6 +351,7 @@ class Engine {
|
|
|
316
351
|
}
|
|
317
352
|
|
|
318
353
|
peer.tracks.forEach((track) => track.close());
|
|
354
|
+
peer.reset();
|
|
319
355
|
this.peersRepository.delete(peerId);
|
|
320
356
|
}
|
|
321
357
|
|
|
@@ -407,7 +443,7 @@ class Engine {
|
|
|
407
443
|
tracks.forEach((track) => {
|
|
408
444
|
track.mediaStreamTrack.addEventListener('ended', () => {
|
|
409
445
|
track.unpublish();
|
|
410
|
-
});
|
|
446
|
+
}, { once: true });
|
|
411
447
|
|
|
412
448
|
track.setStopTrackOnPause(Boolean(options?.stopTrackOnPause));
|
|
413
449
|
if (track instanceof VideoTrack) {
|
|
@@ -521,7 +557,9 @@ class Engine {
|
|
|
521
557
|
return new Promise((resolve, reject) => {
|
|
522
558
|
const onSocketStateChange = async (data: SocketObserverEvent) => {
|
|
523
559
|
const { error, state } = data;
|
|
524
|
-
const stopListening = () => this.network.socket.observer
|
|
560
|
+
const stopListening = () => this.network.socket.observer
|
|
561
|
+
.removeListener(SocketIOEvents.State, onSocketStateChange);
|
|
562
|
+
|
|
525
563
|
const isStateNotExpected = [SocketIOEvents.Disconnected, SocketIOEvents.Reconnecting].includes(state);
|
|
526
564
|
|
|
527
565
|
if (error) {
|
|
@@ -542,7 +580,7 @@ class Engine {
|
|
|
542
580
|
}
|
|
543
581
|
};
|
|
544
582
|
|
|
545
|
-
this.network.socket.observer.on(
|
|
583
|
+
this.network.socket.observer.on(SocketIOEvents.State, onSocketStateChange);
|
|
546
584
|
});
|
|
547
585
|
}
|
|
548
586
|
|
|
@@ -657,9 +695,7 @@ class Engine {
|
|
|
657
695
|
channelId: this.channelId,
|
|
658
696
|
});
|
|
659
697
|
|
|
660
|
-
audioObserver.on('message',
|
|
661
|
-
this.channelAudioObserverEventHandler.handle(data);
|
|
662
|
-
});
|
|
698
|
+
audioObserver.on('message', this.channelAudioObserverEventHandle);
|
|
663
699
|
|
|
664
700
|
this.audioObserver = audioObserver;
|
|
665
701
|
this.logger.debug('Successfully create audio observer', logCtx);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { io, Socket } from 'socket.io-client';
|
|
2
2
|
import EnhancedEventEmitter from '../../EnhancedEventEmitter';
|
|
3
|
-
import { SocketIOEvents } from '../../
|
|
3
|
+
import { SocketIOEvents } from '../../types/socket';
|
|
4
4
|
import { LogLevel, LogMessageHandler, SocketResponse } from '../../types/common';
|
|
5
5
|
import Logger from '../Logger';
|
|
6
6
|
|
|
@@ -63,7 +63,7 @@ class SocketIO {
|
|
|
63
63
|
this.connection = connection;
|
|
64
64
|
this.serverUrl = serverUrl;
|
|
65
65
|
|
|
66
|
-
connection.on(
|
|
66
|
+
connection.on(SocketIOEvents.Connect, () => {
|
|
67
67
|
const state = !this.reconnectingAttempt
|
|
68
68
|
? SocketIOEvents.Connected
|
|
69
69
|
: SocketIOEvents.Reconnected;
|
|
@@ -71,39 +71,39 @@ class SocketIO {
|
|
|
71
71
|
this.isConnected = true;
|
|
72
72
|
this.setReconnectingAttempt(0);
|
|
73
73
|
|
|
74
|
-
this.logger.debug(
|
|
74
|
+
this.logger.debug(`connection.on('${SocketIOEvents.Connect}')`, {
|
|
75
75
|
connectionId: connection.id,
|
|
76
76
|
});
|
|
77
77
|
|
|
78
|
-
this.observer.safeEmit(
|
|
78
|
+
this.observer.safeEmit(SocketIOEvents.State, { state });
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
connection.on(
|
|
81
|
+
connection.on(SocketIOEvents.ConnectError, (error: unknown) => {
|
|
82
82
|
this.connectionError = error as string;
|
|
83
|
-
this.logger.error(
|
|
84
|
-
this.observer.safeEmit(
|
|
83
|
+
this.logger.error(`connection.on('${SocketIOEvents.ConnectError}')`, { error });
|
|
84
|
+
this.observer.safeEmit(SocketIOEvents.State, { state: SocketIOEvents.Error, error });
|
|
85
85
|
});
|
|
86
86
|
|
|
87
|
-
connection.on(
|
|
87
|
+
connection.on(SocketIOEvents.Disconnect, ((reason: string) => {
|
|
88
88
|
this.isConnected = false;
|
|
89
89
|
this.setReconnectingAttempt(0);
|
|
90
90
|
this.disconnectReason = reason;
|
|
91
|
-
this.logger.warn(
|
|
92
|
-
this.observer.safeEmit(
|
|
91
|
+
this.logger.warn(`connection.on('${SocketIOEvents.Disconnect}')`, { reason });
|
|
92
|
+
this.observer.safeEmit(SocketIOEvents.State, {
|
|
93
93
|
state: SocketIOEvents.Disconnected,
|
|
94
94
|
code: this.getDisconnectReasonCode(reason),
|
|
95
95
|
});
|
|
96
96
|
}));
|
|
97
97
|
|
|
98
|
-
connection.io.on(
|
|
98
|
+
connection.io.on(SocketIOEvents.ReconnectAttempt, (attempt: number) => {
|
|
99
99
|
this.setReconnectingAttempt(attempt);
|
|
100
|
-
this.logger.warn(
|
|
101
|
-
this.observer.safeEmit(
|
|
100
|
+
this.logger.warn(`connection.on('${SocketIOEvents.ReconnectAttempt}')`, { attempt });
|
|
101
|
+
this.observer.safeEmit(SocketIOEvents.State, { state: SocketIOEvents.Reconnecting });
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
connection.io.on(
|
|
105
|
-
this.logger.debug(
|
|
106
|
-
this.observer.safeEmit(
|
|
104
|
+
connection.io.on(SocketIOEvents.Reconnect, () => {
|
|
105
|
+
this.logger.debug(`connection.on('${SocketIOEvents.Reconnect}')`, { connectionId: connection.id });
|
|
106
|
+
this.observer.safeEmit(SocketIOEvents.State, { state: SocketIOEvents.Reconnect });
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -112,6 +112,7 @@ class SocketIO {
|
|
|
112
112
|
this.connection.offAny();
|
|
113
113
|
this.connection.volatile.offAny();
|
|
114
114
|
this.connection.disconnect();
|
|
115
|
+
this.connection.io.removeAllListeners();
|
|
115
116
|
// we need to reset this counter in order not to get Reconnected event on retry
|
|
116
117
|
this.setReconnectingAttempt(0);
|
|
117
118
|
}
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
DtlsParameters,
|
|
3
3
|
IceParameters,
|
|
4
4
|
Transport,
|
|
5
|
+
TransportEvents,
|
|
5
6
|
TransportOptions,
|
|
6
7
|
} from 'mediasoup-client/lib/Transport';
|
|
7
8
|
import { Device } from 'mediasoup-client';
|
|
@@ -46,9 +47,9 @@ class Network {
|
|
|
46
47
|
|
|
47
48
|
public readonly eventEmitter: EnhancedEventEmitter;
|
|
48
49
|
|
|
49
|
-
public sendTransport?: Transport
|
|
50
|
+
public sendTransport?: Transport<TransportAppData>;
|
|
50
51
|
|
|
51
|
-
public receiveTransport?: Transport
|
|
52
|
+
public receiveTransport?: Transport<TransportAppData>;
|
|
52
53
|
|
|
53
54
|
private readonly logger: Logger;
|
|
54
55
|
|
|
@@ -64,6 +65,44 @@ class Network {
|
|
|
64
65
|
});
|
|
65
66
|
}
|
|
66
67
|
|
|
68
|
+
private removeEventListeners() {
|
|
69
|
+
const { sendTransport, receiveTransport } = this;
|
|
70
|
+
|
|
71
|
+
if (sendTransport) {
|
|
72
|
+
const eventNames: (keyof TransportEvents)[] = [
|
|
73
|
+
'connect',
|
|
74
|
+
'produce',
|
|
75
|
+
'connectionstatechange',
|
|
76
|
+
];
|
|
77
|
+
eventNames.forEach((x) => sendTransport.removeAllListeners(x));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (receiveTransport) {
|
|
81
|
+
const eventNames: (keyof TransportEvents)[] = [
|
|
82
|
+
'connect',
|
|
83
|
+
'produce',
|
|
84
|
+
'connectionstatechange',
|
|
85
|
+
];
|
|
86
|
+
eventNames.forEach((x) => receiveTransport.removeAllListeners(x));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private stopRestartIceAtempts() {
|
|
91
|
+
const { sendTransport, receiveTransport } = this;
|
|
92
|
+
if (sendTransport) {
|
|
93
|
+
clearInterval(sendTransport.appData.restartIceInterval);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (receiveTransport) {
|
|
97
|
+
clearInterval(receiveTransport.appData.restartIceInterval);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public reset() {
|
|
102
|
+
this.stopRestartIceAtempts();
|
|
103
|
+
this.removeEventListeners();
|
|
104
|
+
}
|
|
105
|
+
|
|
67
106
|
async closeRemoteProducer(producerId: string): Promise<void> {
|
|
68
107
|
await this.socket.request(MEDIASOUP_EVENTS.producerClose, {
|
|
69
108
|
peerId: this.socket.id,
|
|
@@ -187,6 +226,12 @@ class Network {
|
|
|
187
226
|
clearInterval(transport.appData.restartIceInterval);
|
|
188
227
|
transport.appData.restartIceInterval = undefined;
|
|
189
228
|
}
|
|
229
|
+
|
|
230
|
+
if (state === 'connected') {
|
|
231
|
+
setTimeout(() => this.logTransportDetails(transport), 1500);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return;
|
|
190
235
|
}
|
|
191
236
|
|
|
192
237
|
if (['disconnected', 'failed'].includes(state)) {
|
|
@@ -252,7 +297,13 @@ class Network {
|
|
|
252
297
|
this.logger.debug('Stop receiveTransport.restartIce() retries', { recvTransportId: transport.id });
|
|
253
298
|
clearInterval(transport.appData.restartIceInterval);
|
|
254
299
|
transport.appData.restartIceInterval = undefined;
|
|
300
|
+
|
|
301
|
+
if (state === 'connected') {
|
|
302
|
+
setTimeout(() => this.logTransportDetails(transport), 1500);
|
|
303
|
+
}
|
|
255
304
|
}
|
|
305
|
+
|
|
306
|
+
return;
|
|
256
307
|
}
|
|
257
308
|
|
|
258
309
|
if (['disconnected', 'failed'].includes(state)) {
|
|
@@ -295,9 +346,9 @@ class Network {
|
|
|
295
346
|
try {
|
|
296
347
|
const iceParameters = await this.getIceParameters(transport);
|
|
297
348
|
await transport.restartIce({ iceParameters });
|
|
298
|
-
this.logger.
|
|
349
|
+
this.logger.info('restartIce completed', { iceParameters });
|
|
299
350
|
} catch (error) {
|
|
300
|
-
this.logger.error('restartIce
|
|
351
|
+
this.logger.error('restartIce error', { error });
|
|
301
352
|
}
|
|
302
353
|
}
|
|
303
354
|
|
|
@@ -459,10 +510,9 @@ class Network {
|
|
|
459
510
|
) ?? [];
|
|
460
511
|
const localCandidate: Record<string, unknown> | undefined = stats.get(String(pair?.localCandidateId || '-'));
|
|
461
512
|
const remoteCandidate: Record<string, unknown> | undefined = stats.get(String(pair?.remoteCandidateId || '-'));
|
|
462
|
-
|
|
463
|
-
this.logger.info('Detailed WebRTC transport stats', {
|
|
513
|
+
const detailedStats: Record<string, any> = {
|
|
464
514
|
hasNominatedPair: !!pair,
|
|
465
|
-
|
|
515
|
+
transportId: transport.id,
|
|
466
516
|
iceRole: transportStats?.iceRole,
|
|
467
517
|
iceState: transportStats?.iceState,
|
|
468
518
|
dtlsRole: transportStats?.dtlsRole,
|
|
@@ -478,6 +528,8 @@ class Network {
|
|
|
478
528
|
relatedAddress: localCandidate?.relatedAddress,
|
|
479
529
|
relatedPort: localCandidate?.relatedPort,
|
|
480
530
|
transportId: localCandidate?.transportId,
|
|
531
|
+
relayProtocol: localCandidate?.relayProtocol,
|
|
532
|
+
url: localCandidate?.url,
|
|
481
533
|
},
|
|
482
534
|
remote: {
|
|
483
535
|
address: remoteCandidate?.address,
|
|
@@ -488,7 +540,13 @@ class Network {
|
|
|
488
540
|
protocol: remoteCandidate?.protocol,
|
|
489
541
|
transportId: remoteCandidate?.transportId,
|
|
490
542
|
},
|
|
491
|
-
}
|
|
543
|
+
};
|
|
544
|
+
|
|
545
|
+
if (pair?.totalRoundTripTime && pair?.responsesReceived) {
|
|
546
|
+
detailedStats.pairRoundTripTime = Math.round((pair.totalRoundTripTime / pair.responsesReceived) * 1000);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
this.logger.info('Detailed WebRTC transport stats', detailedStats);
|
|
492
550
|
} catch (error: unknown) {
|
|
493
551
|
this.logger.error('Failed to log detailed WebRTC transport stats', {
|
|
494
552
|
error: serializeError(error),
|
package/src/types/media.ts
CHANGED
|
@@ -97,13 +97,13 @@ export interface MediaTracksFactory {
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
export type ProducerAppData = AppData & {
|
|
100
|
-
peerId: string
|
|
101
|
-
label: TrackLabel
|
|
102
|
-
maxSpatialLayer: number
|
|
103
|
-
encodings?: RtpEncodingParameters[]
|
|
104
|
-
codecOptions?: ProducerCodecOptions
|
|
105
|
-
trackTransformParams?: TrackTransformParams
|
|
106
|
-
preferredCodec?: string
|
|
107
|
-
codec?: RtpCodecCapability
|
|
108
|
-
keyFrameRequestDelay?: number
|
|
100
|
+
peerId: string;
|
|
101
|
+
label: TrackLabel;
|
|
102
|
+
maxSpatialLayer: number;
|
|
103
|
+
encodings?: RtpEncodingParameters[];
|
|
104
|
+
codecOptions?: ProducerCodecOptions;
|
|
105
|
+
trackTransformParams?: TrackTransformParams;
|
|
106
|
+
preferredCodec?: string;
|
|
107
|
+
codec?: RtpCodecCapability;
|
|
108
|
+
keyFrameRequestDelay?: number;
|
|
109
109
|
};
|
package/src/types/network.ts
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// eslint-disable-next-line import/prefer-default-export
|
|
2
|
+
export enum SocketIOEvents {
|
|
3
|
+
Connect = 'connect',
|
|
4
|
+
Connected = 'connected',
|
|
5
|
+
ConnectError = 'connect_error',
|
|
6
|
+
|
|
7
|
+
Reconnect = 'reconnect',
|
|
8
|
+
Reconnecting = 'reconnecting',
|
|
9
|
+
Reconnected = 'reconnected',
|
|
10
|
+
ReconnectAttempt = 'reconnect_attempt',
|
|
11
|
+
|
|
12
|
+
Disconnect = 'disconnect',
|
|
13
|
+
Disconnected = 'disconnected',
|
|
14
|
+
Error = 'error',
|
|
15
|
+
State = 'state',
|
|
16
|
+
}
|