@observertc/observer-js 1.0.1-c3edea3.0 → 1.0.1-c9e7581.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/lib/ObservedCall.d.ts +43 -7
- package/lib/ObservedCall.d.ts.map +1 -1
- package/lib/ObservedCall.js +142 -14
- package/lib/ObservedCallEventMonitor.d.ts +104 -0
- package/lib/ObservedCallEventMonitor.d.ts.map +1 -0
- package/lib/ObservedCallEventMonitor.js +314 -0
- package/lib/ObservedCallSummary.d.ts +18 -0
- package/lib/ObservedCallSummary.d.ts.map +1 -0
- package/lib/ObservedClient.d.ts +71 -11
- package/lib/ObservedClient.d.ts.map +1 -1
- package/lib/ObservedClient.js +509 -72
- package/lib/ObservedClientEventMonitor.d.ts +89 -0
- package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
- package/lib/ObservedClientEventMonitor.js +247 -0
- package/lib/ObservedClientSummary.d.ts +23 -0
- package/lib/ObservedClientSummary.d.ts.map +1 -0
- package/lib/ObservedClientSummary.js +2 -0
- package/lib/ObservedDataChannel.d.ts +6 -0
- package/lib/ObservedDataChannel.d.ts.map +1 -1
- package/lib/ObservedDataChannel.js +30 -0
- package/lib/ObservedIceCandidatePair.d.ts +6 -1
- package/lib/ObservedIceCandidatePair.d.ts.map +1 -1
- package/lib/ObservedIceCandidatePair.js +45 -1
- package/lib/ObservedIceTransport.d.ts +4 -0
- package/lib/ObservedIceTransport.d.ts.map +1 -1
- package/lib/ObservedIceTransport.js +28 -0
- package/lib/ObservedInboundTrack.d.ts +3 -0
- package/lib/ObservedInboundTrack.d.ts.map +1 -1
- package/lib/ObservedInboundTrack.js +3 -0
- package/lib/ObservedOutboundTrack.d.ts +3 -0
- package/lib/ObservedOutboundTrack.d.ts.map +1 -1
- package/lib/ObservedOutboundTrack.js +3 -0
- package/lib/ObservedPeerConnection.d.ts +36 -2
- package/lib/ObservedPeerConnection.d.ts.map +1 -1
- package/lib/ObservedPeerConnection.js +184 -29
- package/lib/ObservedTURN.d.ts +31 -0
- package/lib/ObservedTURN.d.ts.map +1 -0
- package/lib/ObservedTURN.js +58 -0
- package/lib/ObservedTurnServer.d.ts +25 -0
- package/lib/ObservedTurnServer.d.ts.map +1 -0
- package/lib/ObservedTurnServer.js +59 -0
- package/lib/Observer.d.ts +43 -22
- package/lib/Observer.d.ts.map +1 -1
- package/lib/Observer.js +126 -40
- package/lib/ObserverEventMonitor.d.ts +138 -0
- package/lib/ObserverEventMonitor.d.ts.map +1 -0
- package/lib/ObserverEventMonitor.js +433 -0
- package/lib/ObserverSummary.d.ts +13 -0
- package/lib/ObserverSummary.d.ts.map +1 -0
- package/lib/ObserverSummary.js +2 -0
- package/lib/common/utils.d.ts +2 -1
- package/lib/common/utils.d.ts.map +1 -1
- package/lib/common/utils.js +11 -3
- package/lib/index.d.ts +6 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +9 -1
- package/lib/schema/ClientEventTypes.d.ts +228 -0
- package/lib/schema/ClientEventTypes.d.ts.map +1 -0
- package/lib/schema/ClientEventTypes.js +41 -0
- package/lib/schema/{metaTypes.d.ts → ClientMetaTypes.d.ts} +2 -2
- package/lib/schema/ClientMetaTypes.d.ts.map +1 -0
- package/lib/schema/ClientMetaTypes.js +16 -0
- package/lib/schema/ClientSample.d.ts +1 -1
- package/lib/schema/ClientSample.d.ts.map +1 -1
- package/lib/updaters/CallUpdater.d.ts.map +1 -0
- package/lib/updaters/CallUpdater.js +2 -0
- package/lib/updaters/ObserverUpdater.d.ts +5 -0
- package/lib/updaters/ObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/ObserverUpdater.js +2 -0
- package/lib/updaters/OnAllCallObserverUpdater.d.ts +15 -0
- package/lib/updaters/OnAllCallObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAllCallObserverUpdater.js +50 -0
- package/lib/updaters/OnAllClientCallUpdater.d.ts +15 -0
- package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAllClientCallUpdater.js +53 -0
- package/lib/updaters/OnAnyCallObserverUpdater.d.ts +12 -0
- package/lib/updaters/OnAnyCallObserverUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAnyCallObserverUpdater.js +37 -0
- package/lib/updaters/OnAnyClientCallUpdater.d.ts +12 -0
- package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -0
- package/lib/updaters/OnAnyClientCallUpdater.js +36 -0
- package/lib/updaters/OnIntervalUpdater.d.ts +10 -0
- package/lib/updaters/OnIntervalUpdater.d.ts.map +1 -0
- package/lib/updaters/OnIntervalUpdater.js +17 -0
- package/lib/updaters/Updater.d.ts +6 -0
- package/lib/updaters/Updater.d.ts.map +1 -0
- package/lib/updaters/Updater.js +2 -0
- package/lib/utils/MediasoupRemoteTrackResolver.d.ts +25 -0
- package/lib/utils/MediasoupRemoteTrackResolver.d.ts.map +1 -0
- package/lib/utils/MediasoupRemoteTrackResolver.js +110 -0
- package/package.json +1 -1
- package/src/ObservedCall.ts +222 -17
- package/src/ObservedCallEventMonitor.ts +392 -0
- package/src/ObservedCallSummary.ts +22 -0
- package/src/ObservedClient.ts +608 -79
- package/src/ObservedClientEventMonitor.ts +301 -0
- package/src/ObservedClientSummary.ts +24 -0
- package/src/ObservedDataChannel.ts +32 -0
- package/src/ObservedIceCandidatePair.ts +44 -2
- package/src/ObservedIceTransport.ts +29 -0
- package/src/ObservedInboundTrack.ts +5 -0
- package/src/ObservedOutboundTrack.ts +5 -0
- package/src/ObservedPeerConnection.ts +219 -46
- package/src/ObservedTURN.ts +86 -0
- package/src/ObservedTurnServer.ts +72 -0
- package/src/Observer.ts +179 -64
- package/src/ObserverEventMonitor.ts +551 -0
- package/src/ObserverSummary.ts +15 -0
- package/src/common/utils.ts +12 -2
- package/src/index.ts +6 -1
- package/src/schema/ClientEventTypes.ts +280 -0
- package/src/schema/{metaTypes.ts → ClientMetaTypes.ts} +1 -1
- package/src/schema/ClientSample.ts +1 -1
- package/src/updaters/ObserverUpdater.ts +5 -0
- package/src/updaters/OnAllCallObserverUpdater.ts +59 -0
- package/src/updaters/OnAllClientCallUpdater.ts +61 -0
- package/src/updaters/OnAnyCallObserverUpdater.ts +41 -0
- package/src/updaters/OnAnyClientCallUpdater.ts +39 -0
- package/src/updaters/OnIntervalUpdater.ts +19 -0
- package/src/updaters/Updater.ts +5 -0
- package/src/utils/MediasoupRemoteTrackResolver.ts +155 -0
- package/tsconfig.json +1 -1
- package/lib/schema/eventTypes.d.ts +0 -33
- package/lib/schema/eventTypes.d.ts.map +0 -1
- package/lib/schema/eventTypes.js +0 -38
- package/lib/schema/metaTypes.d.ts.map +0 -1
- package/lib/schema/metaTypes.js +0 -16
- package/lib/utils/CallUpdater.d.ts.map +0 -1
- package/lib/utils/OnAllClientCallUpdater.d.ts +0 -16
- package/lib/utils/OnAllClientCallUpdater.d.ts.map +0 -1
- package/lib/utils/OnAllClientCallUpdater.js +0 -58
- package/lib/utils/onAnyClientCallUpdater.d.ts +0 -14
- package/lib/utils/onAnyClientCallUpdater.d.ts.map +0 -1
- package/lib/utils/onAnyClientCallUpdater.js +0 -51
- package/src/schema/eventTypes.ts +0 -36
- package/src/utils/OnAllClientCallUpdater.ts +0 -68
- package/src/utils/onAnyClientCallUpdater.ts +0 -59
- /package/lib/{utils/CallUpdater.js → ObservedCallSummary.js} +0 -0
- /package/lib/{utils → updaters}/CallUpdater.d.ts +0 -0
- /package/src/{utils → updaters}/CallUpdater.ts +0 -0
|
@@ -19,6 +19,8 @@ import { ObservedRemoteOutboundRtp } from './ObservedRemoteOutboundRtp';
|
|
|
19
19
|
import { ObservedInboundTrack } from './ObservedInboundTrack';
|
|
20
20
|
import { ObservedOutboundTrack } from './ObservedOutboundTrack';
|
|
21
21
|
import { CalculatedScore } from './scores/CalculatedScore';
|
|
22
|
+
import { ObservedTurnServer } from './ObservedTurnServer';
|
|
23
|
+
import { getMedian } from './common/utils';
|
|
22
24
|
|
|
23
25
|
const logger = createLogger('ObservedPeerConnection');
|
|
24
26
|
|
|
@@ -70,7 +72,27 @@ export type ObservedPeerConnectionEvents = {
|
|
|
70
72
|
'removed-peer-connection-transport': [ObservedPeerConnectionTransport];
|
|
71
73
|
'removed-remote-inbound-rtp': [ObservedRemoteInboundRtp];
|
|
72
74
|
'removed-remote-outbound-rtp': [ObservedRemoteOutboundRtp];
|
|
73
|
-
|
|
75
|
+
'updated-inbound-rtp': [ObservedInboundRtp];
|
|
76
|
+
'updated-outbound-rtp': [ObservedOutboundRtp];
|
|
77
|
+
'updated-inbound-track': [ObservedInboundTrack];
|
|
78
|
+
'updated-outbound-track': [ObservedOutboundTrack];
|
|
79
|
+
'updated-ice-candidate-pair': [ObservedIceCandidatePair];
|
|
80
|
+
'updated-ice-transport': [ObservedIceTransport];
|
|
81
|
+
'updated-peer-connection-transport': [ObservedPeerConnectionTransport];
|
|
82
|
+
'updated-media-source': [ObservedMediaSource];
|
|
83
|
+
'updated-media-playout': [ObservedMediaPlayout];
|
|
84
|
+
'updated-data-channel': [ObservedDataChannel];
|
|
85
|
+
'updated-ice-candidate': [ObservedIceCandidate];
|
|
86
|
+
'updated-certificate': [ObservedCertificate];
|
|
87
|
+
'updated-codec': [ObservedCodec];
|
|
88
|
+
'updated-remote-inbound-rtp': [ObservedRemoteInboundRtp];
|
|
89
|
+
'updated-remote-outbound-rtp': [ObservedRemoteOutboundRtp];
|
|
90
|
+
'muted-inbound-track': [ObservedInboundTrack];
|
|
91
|
+
'muted-outbound-track': [ObservedOutboundTrack];
|
|
92
|
+
'unmuted-inbound-track': [ObservedInboundTrack];
|
|
93
|
+
'unmuted-outbound-track': [ObservedOutboundTrack];
|
|
94
|
+
|
|
95
|
+
'update': [],
|
|
74
96
|
close: [];
|
|
75
97
|
};
|
|
76
98
|
|
|
@@ -106,11 +128,19 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
106
128
|
public closedAt?: number;
|
|
107
129
|
public updated = Date.now();
|
|
108
130
|
|
|
131
|
+
public connectionState?: string;
|
|
132
|
+
public iceConnectionState?: string;
|
|
133
|
+
public iceGatheringState?: string;
|
|
134
|
+
|
|
135
|
+
public availableIncomingBitrate = 0;
|
|
136
|
+
public availableOutgoingBitrate = 0;
|
|
109
137
|
public totalInboundPacketsLost = 0;
|
|
110
138
|
public totalInboundPacketsReceived = 0;
|
|
111
139
|
public totalOutboundPacketsSent = 0;
|
|
112
140
|
public totalDataChannelBytesSent = 0;
|
|
113
141
|
public totalDataChannelBytesReceived = 0;
|
|
142
|
+
public totalDataChannelMessagesSent = 0;
|
|
143
|
+
public totalDataChannelMessagesReceived = 0;
|
|
114
144
|
|
|
115
145
|
public totalSentAudioBytes = 0;
|
|
116
146
|
public totalSentVideoBytes = 0;
|
|
@@ -126,6 +156,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
126
156
|
public deltaOutboundPacketsSent = 0;
|
|
127
157
|
public deltaDataChannelBytesSent = 0;
|
|
128
158
|
public deltaDataChannelBytesReceived = 0;
|
|
159
|
+
public deltaDataChannelMessagesSent = 0;
|
|
160
|
+
public deltaDataChannelMessagesReceived = 0;
|
|
129
161
|
public deltaInboundReceivedBytes = 0;
|
|
130
162
|
public deltaOutboundSentBytes = 0;
|
|
131
163
|
|
|
@@ -135,6 +167,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
135
167
|
public deltaReceivedVideoPackets = 0;
|
|
136
168
|
public deltaSentAudioBytes = 0;
|
|
137
169
|
public deltaSentVideoBytes = 0;
|
|
170
|
+
public deltaTransportSentBytes = 0;
|
|
171
|
+
public deltaTransportReceivedBytes = 0;
|
|
138
172
|
|
|
139
173
|
public receivingPacketsPerSecond = 0;
|
|
140
174
|
public sendingPacketsPerSecond = 0;
|
|
@@ -143,12 +177,13 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
143
177
|
public receivingAudioBitrate = 0;
|
|
144
178
|
public receivingVideoBitrate = 0;
|
|
145
179
|
|
|
146
|
-
public
|
|
147
|
-
public
|
|
180
|
+
public currentRttInMs?: number;
|
|
181
|
+
public currentJitter?: number;
|
|
148
182
|
|
|
149
183
|
public usingTCP = false;
|
|
150
184
|
public usingTURN = false;
|
|
151
185
|
|
|
186
|
+
public observedTurnServer?: ObservedTurnServer;
|
|
152
187
|
public readonly observedCertificates = new Map<string, ObservedCertificate>();
|
|
153
188
|
public readonly observedCodecs = new Map<string, ObservedCodec>();
|
|
154
189
|
public readonly observedDataChannels = new Map<string, ObservedDataChannel>();
|
|
@@ -239,6 +274,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
239
274
|
.filter((pair) => pair !== undefined) as ObservedIceCandidatePair[];
|
|
240
275
|
}
|
|
241
276
|
|
|
277
|
+
public get selectedIceCandiadtePairForTurn() {
|
|
278
|
+
return this.selectedIceCandidatePairs
|
|
279
|
+
.filter((pair) =>
|
|
280
|
+
pair.getLocalCandidate()?.candidateType === 'relay' &&
|
|
281
|
+
pair.getRemoteCandidate()?.url?.startsWith('turn:')
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
242
285
|
public close() {
|
|
243
286
|
if (this.closed) return;
|
|
244
287
|
this.closed = true;
|
|
@@ -259,6 +302,10 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
259
302
|
this.observedRemoteInboundRtps.clear();
|
|
260
303
|
this.observedRemoteOutboundRtps.clear();
|
|
261
304
|
|
|
305
|
+
this.client.call.observer.observedTURN.removePeerConnection(this);
|
|
306
|
+
|
|
307
|
+
if (!this.closedAt) this.closedAt = Date.now();
|
|
308
|
+
|
|
262
309
|
this.emit('close');
|
|
263
310
|
}
|
|
264
311
|
|
|
@@ -266,6 +313,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
266
313
|
if (this.closed) return;
|
|
267
314
|
this._visited = true;
|
|
268
315
|
|
|
316
|
+
this.availableIncomingBitrate = 0;
|
|
317
|
+
this.availableOutgoingBitrate = 0;
|
|
269
318
|
this.deltaInboundPacketsLost = 0;
|
|
270
319
|
this.deltaInboundPacketsReceived = 0;
|
|
271
320
|
this.deltaOutboundPacketsSent = 0;
|
|
@@ -279,6 +328,9 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
279
328
|
this.deltaReceivedVideoPackets = 0;
|
|
280
329
|
this.deltaSentAudioBytes = 0;
|
|
281
330
|
this.deltaSentVideoBytes = 0;
|
|
331
|
+
this.deltaTransportReceivedBytes = 0;
|
|
332
|
+
this.deltaTransportSentBytes = 0;
|
|
333
|
+
|
|
282
334
|
this.sendingAudioBitrate = 0;
|
|
283
335
|
this.sendingVideoBitrate = 0;
|
|
284
336
|
this.receivingAudioBitrate = 0;
|
|
@@ -287,6 +339,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
287
339
|
const now = Date.now();
|
|
288
340
|
const elapsedTimeInMs = now - this.updated;
|
|
289
341
|
const elapsedTimeInSec = elapsedTimeInMs / 1000;
|
|
342
|
+
const rttMeasurementsInSec: number[] = [];
|
|
343
|
+
const jitterMeasurements: number[] = [];
|
|
290
344
|
|
|
291
345
|
if (sample.certificates) {
|
|
292
346
|
for (const certificate of sample.certificates) {
|
|
@@ -300,7 +354,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
300
354
|
}
|
|
301
355
|
if (sample.dataChannels) {
|
|
302
356
|
for (const dataChannel of sample.dataChannels) {
|
|
303
|
-
this._updateDataChannelStats(dataChannel);
|
|
357
|
+
const observedDataChannel = this._updateDataChannelStats(dataChannel);
|
|
358
|
+
|
|
359
|
+
if (!observedDataChannel) continue;
|
|
360
|
+
|
|
361
|
+
this.deltaDataChannelBytesSent += observedDataChannel.deltaBytesSent;
|
|
362
|
+
this.deltaDataChannelBytesReceived += observedDataChannel.deltaBytesReceived;
|
|
363
|
+
this.deltaDataChannelMessagesSent += observedDataChannel.deltaMessagesSent;
|
|
364
|
+
this.deltaDataChannelMessagesReceived += observedDataChannel.deltaMessagesReceived;
|
|
304
365
|
}
|
|
305
366
|
}
|
|
306
367
|
if (sample.iceCandidates) {
|
|
@@ -310,12 +371,29 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
310
371
|
}
|
|
311
372
|
if (sample.iceCandidatePairs) {
|
|
312
373
|
for (const iceCandidatePair of sample.iceCandidatePairs) {
|
|
313
|
-
this._updateIceCandidatePairStats(iceCandidatePair);
|
|
374
|
+
const observedCandidatePair = this._updateIceCandidatePairStats(iceCandidatePair);
|
|
375
|
+
|
|
376
|
+
if (!observedCandidatePair) continue;
|
|
377
|
+
|
|
378
|
+
if (observedCandidatePair.currentRoundTripTime) {
|
|
379
|
+
rttMeasurementsInSec.push(observedCandidatePair.currentRoundTripTime);
|
|
380
|
+
}
|
|
381
|
+
if (observedCandidatePair.availableIncomingBitrate) {
|
|
382
|
+
this.availableIncomingBitrate += observedCandidatePair.availableIncomingBitrate;
|
|
383
|
+
}
|
|
384
|
+
if (observedCandidatePair.availableOutgoingBitrate) {
|
|
385
|
+
this.availableOutgoingBitrate += observedCandidatePair.availableOutgoingBitrate;
|
|
386
|
+
}
|
|
314
387
|
}
|
|
315
388
|
}
|
|
316
389
|
if (sample.iceTransports) {
|
|
317
390
|
for (const iceTransport of sample.iceTransports) {
|
|
318
|
-
this._updateIceTransportStats(iceTransport);
|
|
391
|
+
const observedIceTransport = this._updateIceTransportStats(iceTransport);
|
|
392
|
+
|
|
393
|
+
if (!observedIceTransport) return;
|
|
394
|
+
|
|
395
|
+
observedIceTransport.bytesReceived;
|
|
396
|
+
|
|
319
397
|
}
|
|
320
398
|
}
|
|
321
399
|
if (sample.inboundRtps) {
|
|
@@ -338,6 +416,10 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
338
416
|
this.deltaReceivedVideoPackets += observedInboundRtp.deltaReceivedPackets;
|
|
339
417
|
break;
|
|
340
418
|
}
|
|
419
|
+
|
|
420
|
+
if (observedInboundRtp.jitter) {
|
|
421
|
+
jitterMeasurements.push(observedInboundRtp.jitter);
|
|
422
|
+
}
|
|
341
423
|
}
|
|
342
424
|
}
|
|
343
425
|
if (sample.mediaPlayouts) {
|
|
@@ -374,12 +456,21 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
374
456
|
}
|
|
375
457
|
if (sample.peerConnectionTransports) {
|
|
376
458
|
for (const peerConnectionTransport of sample.peerConnectionTransports) {
|
|
377
|
-
this._updatePeerConnectionTransportStats(peerConnectionTransport);
|
|
459
|
+
const observedTransport = this._updatePeerConnectionTransportStats(peerConnectionTransport);
|
|
460
|
+
|
|
461
|
+
if (!observedTransport) continue;
|
|
462
|
+
|
|
378
463
|
}
|
|
379
464
|
}
|
|
380
465
|
if (sample.remoteInboundRtps) {
|
|
381
466
|
for (const remoteInboundRtp of sample.remoteInboundRtps) {
|
|
382
|
-
this._updateRemoteInboundRtpStats(remoteInboundRtp);
|
|
467
|
+
const observedRemoteInboundRtp = this._updateRemoteInboundRtpStats(remoteInboundRtp);
|
|
468
|
+
|
|
469
|
+
if (!observedRemoteInboundRtp) continue;
|
|
470
|
+
|
|
471
|
+
if (observedRemoteInboundRtp.roundTripTime) {
|
|
472
|
+
rttMeasurementsInSec.push(observedRemoteInboundRtp.roundTripTime);
|
|
473
|
+
}
|
|
383
474
|
}
|
|
384
475
|
}
|
|
385
476
|
if (sample.remoteOutboundRtps) {
|
|
@@ -408,6 +499,8 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
408
499
|
this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
|
|
409
500
|
this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
|
|
410
501
|
this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
|
|
502
|
+
this.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
|
|
503
|
+
this.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
|
|
411
504
|
this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
|
|
412
505
|
this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
|
|
413
506
|
this.totalSentAudioBytes += this.deltaSentAudioBytes;
|
|
@@ -419,20 +512,55 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
419
512
|
|
|
420
513
|
this.receivingPacketsPerSecond = this.deltaInboundPacketsReceived / elapsedTimeInSec;
|
|
421
514
|
this.sendingPacketsPerSecond = this.deltaOutboundPacketsSent / elapsedTimeInSec;
|
|
422
|
-
this.sendingAudioBitrate = this.deltaSentAudioBytes * 8 / elapsedTimeInSec;
|
|
423
|
-
this.sendingVideoBitrate = this.deltaSentVideoBytes * 8 / elapsedTimeInSec;
|
|
424
|
-
this.receivingAudioBitrate = this.deltaReceivedAudioBytes * 8 / elapsedTimeInSec;
|
|
425
|
-
this.receivingVideoBitrate = this.deltaReceivedVideoBytes * 8 / elapsedTimeInSec;
|
|
426
|
-
|
|
515
|
+
this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / elapsedTimeInSec;
|
|
516
|
+
this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / elapsedTimeInSec;
|
|
517
|
+
this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / elapsedTimeInSec;
|
|
518
|
+
this.receivingVideoBitrate = (this.deltaReceivedVideoBytes * 8) / elapsedTimeInSec;
|
|
519
|
+
|
|
520
|
+
if (rttMeasurementsInSec.length > 0) {
|
|
521
|
+
this.currentRttInMs = getMedian(rttMeasurementsInSec, false) * 1000;
|
|
522
|
+
} else {
|
|
523
|
+
this.currentRttInMs = undefined;
|
|
524
|
+
}
|
|
525
|
+
if (jitterMeasurements.length > 0) {
|
|
526
|
+
this.currentJitter = getMedian(jitterMeasurements, false);
|
|
527
|
+
} else {
|
|
528
|
+
this.currentJitter = undefined;
|
|
529
|
+
}
|
|
530
|
+
const wasUsingTURN = this.usingTURN;
|
|
427
531
|
const selectedIceCandidatePairs = this.selectedIceCandidatePairs;
|
|
532
|
+
const selectedCandidatePairForTurn: ObservedIceCandidatePair[] = [];
|
|
533
|
+
|
|
534
|
+
this.usingTCP = false;
|
|
535
|
+
this.usingTURN = false;
|
|
428
536
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
537
|
+
for (const selectedCandidatePair of selectedIceCandidatePairs) {
|
|
538
|
+
if (selectedCandidatePair.getLocalCandidate()?.protocol === 'tcp') {
|
|
539
|
+
this.usingTCP = true;
|
|
540
|
+
}
|
|
541
|
+
if (selectedCandidatePair.getLocalCandidate()?.candidateType === 'relay' && selectedCandidatePair.getRemoteCandidate()?.url?.startsWith('turn:')) {
|
|
542
|
+
selectedCandidatePairForTurn.push(selectedCandidatePair);
|
|
543
|
+
this.usingTURN = true;
|
|
544
|
+
}
|
|
545
|
+
this.deltaTransportReceivedBytes += selectedCandidatePair.deltaBytesReceived;
|
|
546
|
+
this.deltaTransportSentBytes += selectedCandidatePair.deltaBytesSent;
|
|
547
|
+
}
|
|
432
548
|
|
|
549
|
+
if (this.usingTURN) {
|
|
550
|
+
if (!this.observedTurnServer) {
|
|
551
|
+
this.observedTurnServer = this.client.call.observer.observedTURN.addPeerConnection(this);
|
|
552
|
+
}
|
|
553
|
+
this.observedTurnServer?.updateTurnUsage(...selectedCandidatePairForTurn);
|
|
554
|
+
} else if (wasUsingTURN) {
|
|
555
|
+
if (!this.usingTURN) {
|
|
556
|
+
this.client.call.observer.observedTURN.removePeerConnection(this);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
433
559
|
this.calculatedScore.value = sample.score;
|
|
434
560
|
this.updated = now;
|
|
435
561
|
this._checkVisited();
|
|
562
|
+
|
|
563
|
+
this.emit('update');
|
|
436
564
|
}
|
|
437
565
|
|
|
438
566
|
private _checkVisited() {
|
|
@@ -540,12 +668,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
540
668
|
|
|
541
669
|
observedCertificate = new ObservedCertificate(stats.timestamp, stats.id, this);
|
|
542
670
|
|
|
671
|
+
observedCertificate.update(stats);
|
|
672
|
+
|
|
543
673
|
this.observedCertificates.set(stats.id, observedCertificate);
|
|
544
674
|
this.emit('added-certificate', observedCertificate);
|
|
675
|
+
} else {
|
|
676
|
+
observedCertificate.update(stats);
|
|
677
|
+
this.emit('updated-certificate', observedCertificate);
|
|
545
678
|
}
|
|
546
679
|
|
|
547
|
-
observedCertificate.update(stats);
|
|
548
|
-
|
|
549
680
|
return observedCertificate;
|
|
550
681
|
}
|
|
551
682
|
|
|
@@ -562,11 +693,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
562
693
|
|
|
563
694
|
observedCodec = new ObservedCodec(stats.timestamp, stats.id, stats.mimeType, this);
|
|
564
695
|
|
|
696
|
+
observedCodec.update(stats);
|
|
697
|
+
|
|
565
698
|
this.observedCodecs.set(stats.id, observedCodec);
|
|
566
699
|
this.emit('added-codec', observedCodec);
|
|
700
|
+
} else {
|
|
701
|
+
observedCodec.update(stats);
|
|
567
702
|
}
|
|
568
|
-
|
|
569
|
-
observedCodec.update(stats);
|
|
703
|
+
this.emit('updated-codec', observedCodec);
|
|
570
704
|
|
|
571
705
|
return observedCodec;
|
|
572
706
|
}
|
|
@@ -584,11 +718,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
584
718
|
|
|
585
719
|
observedDataChannel = new ObservedDataChannel(stats.timestamp, stats.id, this);
|
|
586
720
|
|
|
721
|
+
observedDataChannel.update(stats);
|
|
722
|
+
|
|
587
723
|
this.observedDataChannels.set(stats.id, observedDataChannel);
|
|
588
724
|
this.emit('added-data-channel', observedDataChannel);
|
|
725
|
+
} else {
|
|
726
|
+
observedDataChannel.update(stats);
|
|
589
727
|
}
|
|
590
|
-
|
|
591
|
-
observedDataChannel.update(stats);
|
|
728
|
+
this.emit('updated-data-channel', observedDataChannel);
|
|
592
729
|
|
|
593
730
|
return observedDataChannel;
|
|
594
731
|
}
|
|
@@ -606,11 +743,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
606
743
|
|
|
607
744
|
observedIceCandidate = new ObservedIceCandidate(stats.timestamp, stats.id, this);
|
|
608
745
|
|
|
746
|
+
observedIceCandidate.update(stats);
|
|
747
|
+
|
|
609
748
|
this.observedIceCandidates.set(stats.id, observedIceCandidate);
|
|
610
749
|
this.emit('added-ice-candidate', observedIceCandidate);
|
|
750
|
+
} else {
|
|
751
|
+
observedIceCandidate.update(stats);
|
|
611
752
|
}
|
|
612
|
-
|
|
613
|
-
observedIceCandidate.update(stats);
|
|
753
|
+
this.emit('updated-ice-candidate', observedIceCandidate);
|
|
614
754
|
|
|
615
755
|
return observedIceCandidate;
|
|
616
756
|
}
|
|
@@ -628,11 +768,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
628
768
|
|
|
629
769
|
observedIceCandidatePair = new ObservedIceCandidatePair(stats.timestamp, stats.id, this);
|
|
630
770
|
|
|
771
|
+
observedIceCandidatePair.update(stats);
|
|
772
|
+
|
|
631
773
|
this.observedIceCandidatesPair.set(stats.id, observedIceCandidatePair);
|
|
632
774
|
this.emit('added-ice-candidate-pair', observedIceCandidatePair);
|
|
775
|
+
} else {
|
|
776
|
+
observedIceCandidatePair.update(stats);
|
|
633
777
|
}
|
|
634
|
-
|
|
635
|
-
observedIceCandidatePair.update(stats);
|
|
778
|
+
this.emit('updated-ice-candidate-pair', observedIceCandidatePair);
|
|
636
779
|
|
|
637
780
|
return observedIceCandidatePair;
|
|
638
781
|
}
|
|
@@ -650,11 +793,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
650
793
|
|
|
651
794
|
observedIceTransport = new ObservedIceTransport(stats.timestamp, stats.id, this);
|
|
652
795
|
|
|
796
|
+
observedIceTransport.update(stats);
|
|
797
|
+
|
|
653
798
|
this.observedIceTransports.set(stats.id, observedIceTransport);
|
|
654
799
|
this.emit('added-ice-transport', observedIceTransport);
|
|
800
|
+
} else {
|
|
801
|
+
observedIceTransport.update(stats);
|
|
655
802
|
}
|
|
656
|
-
|
|
657
|
-
observedIceTransport.update(stats);
|
|
803
|
+
this.emit('updated-ice-transport', observedIceTransport);
|
|
658
804
|
|
|
659
805
|
return observedIceTransport;
|
|
660
806
|
}
|
|
@@ -678,12 +824,15 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
678
824
|
stats.trackIdentifier,
|
|
679
825
|
this
|
|
680
826
|
);
|
|
827
|
+
|
|
828
|
+
observedInboundRtp.update(stats);
|
|
681
829
|
|
|
682
830
|
this.observedInboundRtps.set(stats.ssrc, observedInboundRtp);
|
|
683
831
|
this.emit('added-inbound-rtp', observedInboundRtp);
|
|
832
|
+
} else {
|
|
833
|
+
observedInboundRtp.update(stats);
|
|
684
834
|
}
|
|
685
|
-
|
|
686
|
-
observedInboundRtp.update(stats);
|
|
835
|
+
this.emit('updated-inbound-rtp', observedInboundRtp);
|
|
687
836
|
|
|
688
837
|
return observedInboundRtp;
|
|
689
838
|
}
|
|
@@ -712,11 +861,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
712
861
|
mediaPlayout,
|
|
713
862
|
);
|
|
714
863
|
|
|
864
|
+
observedInboundTrack.update(stats);
|
|
865
|
+
|
|
715
866
|
this.observedInboundTracks.set(stats.id, observedInboundTrack);
|
|
716
867
|
this.emit('added-inbound-track', observedInboundTrack);
|
|
868
|
+
} else {
|
|
869
|
+
observedInboundTrack.update(stats);
|
|
717
870
|
}
|
|
718
|
-
|
|
719
|
-
observedInboundTrack.update(stats);
|
|
871
|
+
this.emit('updated-inbound-track', observedInboundTrack);
|
|
720
872
|
|
|
721
873
|
return observedInboundTrack;
|
|
722
874
|
}
|
|
@@ -739,11 +891,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
739
891
|
this
|
|
740
892
|
);
|
|
741
893
|
|
|
894
|
+
observedMediaPlayout.update(stats);
|
|
895
|
+
|
|
742
896
|
this.observedMediaPlayouts.set(stats.id, observedMediaPlayout);
|
|
743
897
|
this.emit('added-media-playout', observedMediaPlayout);
|
|
898
|
+
} else {
|
|
899
|
+
observedMediaPlayout.update(stats);
|
|
744
900
|
}
|
|
745
|
-
|
|
746
|
-
observedMediaPlayout.update(stats);
|
|
901
|
+
this.emit('updated-media-playout', observedMediaPlayout);
|
|
747
902
|
|
|
748
903
|
return observedMediaPlayout;
|
|
749
904
|
}
|
|
@@ -766,11 +921,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
766
921
|
this
|
|
767
922
|
);
|
|
768
923
|
|
|
924
|
+
observedMediaSource.update(stats);
|
|
925
|
+
|
|
769
926
|
this.observedMediaSources.set(stats.id, observedMediaSource);
|
|
770
927
|
this.emit('added-media-source', observedMediaSource);
|
|
928
|
+
} else {
|
|
929
|
+
observedMediaSource.update(stats);
|
|
771
930
|
}
|
|
772
|
-
|
|
773
|
-
observedMediaSource.update(stats);
|
|
931
|
+
this.emit('updated-media-source', observedMediaSource);
|
|
774
932
|
|
|
775
933
|
return observedMediaSource;
|
|
776
934
|
}
|
|
@@ -794,11 +952,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
794
952
|
this
|
|
795
953
|
);
|
|
796
954
|
|
|
955
|
+
observedOutboundRtp.update(stats);
|
|
956
|
+
|
|
797
957
|
this.observedOutboundRtps.set(stats.ssrc, observedOutboundRtp);
|
|
798
958
|
this.emit('added-outbound-rtp', observedOutboundRtp);
|
|
959
|
+
} else {
|
|
960
|
+
observedOutboundRtp.update(stats);
|
|
799
961
|
}
|
|
800
|
-
|
|
801
|
-
observedOutboundRtp.update(stats);
|
|
962
|
+
this.emit('updated-outbound-rtp', observedOutboundRtp);
|
|
802
963
|
|
|
803
964
|
return observedOutboundRtp;
|
|
804
965
|
}
|
|
@@ -826,11 +987,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
826
987
|
observedMediaSource,
|
|
827
988
|
);
|
|
828
989
|
|
|
990
|
+
observedOutboundTrack.update(stats);
|
|
991
|
+
|
|
829
992
|
this.observedOutboundTracks.set(stats.id, observedOutboundTrack);
|
|
830
993
|
this.emit('added-outbound-track', observedOutboundTrack);
|
|
994
|
+
} else {
|
|
995
|
+
observedOutboundTrack.update(stats);
|
|
831
996
|
}
|
|
832
|
-
|
|
833
|
-
observedOutboundTrack.update(stats);
|
|
997
|
+
this.emit('updated-outbound-track', observedOutboundTrack);
|
|
834
998
|
|
|
835
999
|
return observedOutboundTrack;
|
|
836
1000
|
}
|
|
@@ -848,11 +1012,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
848
1012
|
|
|
849
1013
|
observedPeerConnectionTransport = new ObservedPeerConnectionTransport(stats.timestamp, stats.id, this);
|
|
850
1014
|
|
|
1015
|
+
observedPeerConnectionTransport.update(stats);
|
|
1016
|
+
|
|
851
1017
|
this.observedPeerConnectionTransports.set(stats.id, observedPeerConnectionTransport);
|
|
852
1018
|
this.emit('added-peer-connection-transport', observedPeerConnectionTransport);
|
|
1019
|
+
} else {
|
|
1020
|
+
observedPeerConnectionTransport.update(stats);
|
|
853
1021
|
}
|
|
854
|
-
|
|
855
|
-
observedPeerConnectionTransport.update(stats);
|
|
1022
|
+
this.emit('updated-peer-connection-transport', observedPeerConnectionTransport);
|
|
856
1023
|
|
|
857
1024
|
return observedPeerConnectionTransport;
|
|
858
1025
|
}
|
|
@@ -876,11 +1043,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
876
1043
|
this
|
|
877
1044
|
);
|
|
878
1045
|
|
|
1046
|
+
observedRemoteInboundRtp.update(stats);
|
|
1047
|
+
|
|
879
1048
|
this.observedRemoteInboundRtps.set(stats.ssrc, observedRemoteInboundRtp);
|
|
880
1049
|
this.emit('added-remote-inbound-rtp', observedRemoteInboundRtp);
|
|
1050
|
+
} else {
|
|
1051
|
+
observedRemoteInboundRtp.update(stats);
|
|
881
1052
|
}
|
|
882
|
-
|
|
883
|
-
observedRemoteInboundRtp.update(stats);
|
|
1053
|
+
this.emit('updated-remote-inbound-rtp', observedRemoteInboundRtp);
|
|
884
1054
|
|
|
885
1055
|
return observedRemoteInboundRtp;
|
|
886
1056
|
}
|
|
@@ -904,11 +1074,14 @@ export class ObservedPeerConnection extends EventEmitter {
|
|
|
904
1074
|
this
|
|
905
1075
|
);
|
|
906
1076
|
|
|
1077
|
+
observedRemoteOutboundRtp.update(stats);
|
|
1078
|
+
|
|
907
1079
|
this.observedRemoteOutboundRtps.set(stats.ssrc, observedRemoteOutboundRtp);
|
|
908
1080
|
this.emit('added-remote-outbound-rtp', observedRemoteOutboundRtp);
|
|
1081
|
+
} else {
|
|
1082
|
+
observedRemoteOutboundRtp.update(stats);
|
|
909
1083
|
}
|
|
910
|
-
|
|
911
|
-
observedRemoteOutboundRtp.update(stats);
|
|
1084
|
+
this.emit('updated-remote-outbound-rtp', observedRemoteOutboundRtp);
|
|
912
1085
|
|
|
913
1086
|
return observedRemoteOutboundRtp;
|
|
914
1087
|
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { EventEmitter } from 'stream';
|
|
2
|
+
import { ObservedPeerConnection } from './ObservedPeerConnection';
|
|
3
|
+
import { ObservedTurnServer } from './ObservedTurnServer';
|
|
4
|
+
import { createLogger } from './common/logger';
|
|
5
|
+
|
|
6
|
+
const logger = createLogger('ObservedTURN');
|
|
7
|
+
|
|
8
|
+
export type ObservedTURNEventMap = {
|
|
9
|
+
'update': [ObservedTURN];
|
|
10
|
+
'close': [];
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export declare interface ObservedTURN {
|
|
14
|
+
on<U extends keyof ObservedTURNEventMap>(event: U, listener: (...args: ObservedTURNEventMap[U]) => void): this;
|
|
15
|
+
off<U extends keyof ObservedTURNEventMap>(event: U, listener: (...args: ObservedTURNEventMap[U]) => void): this;
|
|
16
|
+
once<U extends keyof ObservedTURNEventMap>(event: U, listener: (...args: ObservedTURNEventMap[U]) => void): this;
|
|
17
|
+
emit<U extends keyof ObservedTURNEventMap>(event: U, ...args: ObservedTURNEventMap[U]): boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export class ObservedTURN extends EventEmitter {
|
|
21
|
+
public totalBytesSent = 0;
|
|
22
|
+
public totalBytesReceived = 0;
|
|
23
|
+
public totalPacketsSent = 0;
|
|
24
|
+
public totalPacketsReceived = 0;
|
|
25
|
+
|
|
26
|
+
public packetsSentPerSecond = 0;
|
|
27
|
+
public packetsReceivedPerSecond = 0;
|
|
28
|
+
public outboundBitrate = 0;
|
|
29
|
+
public inboundBitrate = 0;
|
|
30
|
+
public numberOfClients = 0;
|
|
31
|
+
|
|
32
|
+
public readonly servers = new Map<string, ObservedTurnServer>();
|
|
33
|
+
|
|
34
|
+
public constructor(
|
|
35
|
+
) {
|
|
36
|
+
super();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public update() {
|
|
40
|
+
const clientIds = new Set<string>();
|
|
41
|
+
|
|
42
|
+
this.packetsReceivedPerSecond = 0;
|
|
43
|
+
this.packetsSentPerSecond = 0;
|
|
44
|
+
this.outboundBitrate = 0;
|
|
45
|
+
this.inboundBitrate = 0;
|
|
46
|
+
|
|
47
|
+
for (const server of this.servers.values()) {
|
|
48
|
+
server.update();
|
|
49
|
+
server.observedPeerConnections.forEach((pc) => clientIds.add(pc.client.clientId));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.numberOfClients = clientIds.size;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public addPeerConnection(peerConnection: ObservedPeerConnection) {
|
|
56
|
+
const turnPairs = peerConnection.selectedIceCandidatePairs.filter((pair) => pair.getLocalCandidate()?.candidateType === 'relay' && pair.getRemoteCandidate()?.url?.startsWith('turn:'));
|
|
57
|
+
|
|
58
|
+
if (turnPairs.length !== 1) {
|
|
59
|
+
return (logger.warn(`Expected exactly one TURN pair, but found for peerconnection ${peerConnection.peerConnectionId}`, turnPairs.length), undefined);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const candidatePair = turnPairs[0];
|
|
63
|
+
const rawUrl = candidatePair.getRemoteCandidate()?.url;
|
|
64
|
+
|
|
65
|
+
if (!rawUrl) {
|
|
66
|
+
return (logger.warn(`No remote candidate URL found for peerconnection ${peerConnection.peerConnectionId}`), undefined);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const turnUrl = new URL(rawUrl);
|
|
70
|
+
const turnServerUrl = `${turnUrl.protocol}//${turnUrl.hostname}:${turnUrl.port}`;
|
|
71
|
+
let turnServer = this.servers.get(turnServerUrl);
|
|
72
|
+
|
|
73
|
+
if (!turnServer) {
|
|
74
|
+
turnServer = new ObservedTurnServer(turnServerUrl, this);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return turnServer;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public removePeerConnection(peerConnection: ObservedPeerConnection) {
|
|
81
|
+
for (const turnServer of this.servers.values()) {
|
|
82
|
+
turnServer.observedPeerConnections.delete(peerConnection.peerConnectionId);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|