@observertc/observer-js 1.0.1-c3edea3.0 → 1.0.1-ec27289.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.
Files changed (125) hide show
  1. package/lib/ObservedCall.d.ts +41 -7
  2. package/lib/ObservedCall.d.ts.map +1 -1
  3. package/lib/ObservedCall.js +125 -13
  4. package/lib/ObservedCallSummary.d.ts +18 -0
  5. package/lib/ObservedCallSummary.d.ts.map +1 -0
  6. package/lib/ObservedClient.d.ts +70 -11
  7. package/lib/ObservedClient.d.ts.map +1 -1
  8. package/lib/ObservedClient.js +394 -72
  9. package/lib/ObservedClientEventMonitor.d.ts +89 -0
  10. package/lib/ObservedClientEventMonitor.d.ts.map +1 -0
  11. package/lib/ObservedClientEventMonitor.js +247 -0
  12. package/lib/ObservedClientSummary.d.ts +23 -0
  13. package/lib/ObservedClientSummary.d.ts.map +1 -0
  14. package/lib/ObservedClientSummary.js +2 -0
  15. package/lib/ObservedDataChannel.d.ts +6 -0
  16. package/lib/ObservedDataChannel.d.ts.map +1 -1
  17. package/lib/ObservedDataChannel.js +30 -0
  18. package/lib/ObservedIceCandidatePair.d.ts +4 -0
  19. package/lib/ObservedIceCandidatePair.d.ts.map +1 -1
  20. package/lib/ObservedIceCandidatePair.js +28 -0
  21. package/lib/ObservedIceTransport.d.ts +4 -0
  22. package/lib/ObservedIceTransport.d.ts.map +1 -1
  23. package/lib/ObservedIceTransport.js +28 -0
  24. package/lib/ObservedInboundTrack.d.ts +2 -0
  25. package/lib/ObservedInboundTrack.d.ts.map +1 -1
  26. package/lib/ObservedInboundTrack.js +2 -0
  27. package/lib/ObservedOutboundTrack.d.ts +2 -0
  28. package/lib/ObservedOutboundTrack.d.ts.map +1 -1
  29. package/lib/ObservedOutboundTrack.js +2 -0
  30. package/lib/ObservedPeerConnection.d.ts +14 -2
  31. package/lib/ObservedPeerConnection.d.ts.map +1 -1
  32. package/lib/ObservedPeerConnection.js +106 -14
  33. package/lib/ObservedTURN.d.ts +31 -0
  34. package/lib/ObservedTURN.d.ts.map +1 -0
  35. package/lib/ObservedTURN.js +58 -0
  36. package/lib/ObservedTurnServer.d.ts +25 -0
  37. package/lib/ObservedTurnServer.d.ts.map +1 -0
  38. package/lib/ObservedTurnServer.js +59 -0
  39. package/lib/Observer.d.ts +38 -21
  40. package/lib/Observer.d.ts.map +1 -1
  41. package/lib/Observer.js +114 -40
  42. package/lib/ObserverSummary.d.ts +13 -0
  43. package/lib/ObserverSummary.d.ts.map +1 -0
  44. package/lib/ObserverSummary.js +2 -0
  45. package/lib/common/utils.d.ts +2 -1
  46. package/lib/common/utils.d.ts.map +1 -1
  47. package/lib/common/utils.js +11 -3
  48. package/lib/index.d.ts +5 -0
  49. package/lib/index.d.ts.map +1 -1
  50. package/lib/index.js +7 -1
  51. package/lib/schema/ClientEventTypes.d.ts +100 -0
  52. package/lib/schema/ClientEventTypes.d.ts.map +1 -0
  53. package/lib/schema/ClientEventTypes.js +38 -0
  54. package/lib/schema/{metaTypes.d.ts → ClientMetaTypes.d.ts} +2 -2
  55. package/lib/schema/ClientMetaTypes.d.ts.map +1 -0
  56. package/lib/schema/ClientMetaTypes.js +16 -0
  57. package/lib/updaters/CallUpdater.d.ts.map +1 -0
  58. package/lib/updaters/CallUpdater.js +2 -0
  59. package/lib/updaters/ObserverUpdater.d.ts +5 -0
  60. package/lib/updaters/ObserverUpdater.d.ts.map +1 -0
  61. package/lib/updaters/ObserverUpdater.js +2 -0
  62. package/lib/updaters/OnAllCallObserverUpdater_.d.ts +13 -0
  63. package/lib/updaters/OnAllCallObserverUpdater_.d.ts.map +1 -0
  64. package/lib/updaters/OnAllCallObserverUpdater_.js +38 -0
  65. package/lib/updaters/OnAllClientCallUpdater.d.ts +13 -0
  66. package/lib/updaters/OnAllClientCallUpdater.d.ts.map +1 -0
  67. package/lib/updaters/OnAllClientCallUpdater.js +37 -0
  68. package/lib/updaters/OnAnyCallObserverUpdater_.d.ts +11 -0
  69. package/lib/updaters/OnAnyCallObserverUpdater_.d.ts.map +1 -0
  70. package/lib/updaters/OnAnyCallObserverUpdater_.js +27 -0
  71. package/lib/updaters/OnAnyClientCallUpdater.d.ts +11 -0
  72. package/lib/updaters/OnAnyClientCallUpdater.d.ts.map +1 -0
  73. package/lib/updaters/OnAnyClientCallUpdater.js +27 -0
  74. package/lib/updaters/OnIntervalUpdater.d.ts +10 -0
  75. package/lib/updaters/OnIntervalUpdater.d.ts.map +1 -0
  76. package/lib/updaters/OnIntervalUpdater.js +17 -0
  77. package/lib/updaters/Updater.d.ts +6 -0
  78. package/lib/updaters/Updater.d.ts.map +1 -0
  79. package/lib/updaters/Updater.js +2 -0
  80. package/package.json +1 -1
  81. package/src/ObservedCall.ts +205 -16
  82. package/src/ObservedCallSummary.ts +22 -0
  83. package/src/ObservedClient.ts +492 -78
  84. package/src/ObservedClientEventMonitor.ts +301 -0
  85. package/src/ObservedClientSummary.ts +24 -0
  86. package/src/ObservedDataChannel.ts +32 -0
  87. package/src/ObservedIceCandidatePair.ts +26 -0
  88. package/src/ObservedIceTransport.ts +29 -0
  89. package/src/ObservedInboundTrack.ts +3 -0
  90. package/src/ObservedOutboundTrack.ts +3 -0
  91. package/src/ObservedPeerConnection.ts +120 -16
  92. package/src/ObservedTURN.ts +86 -0
  93. package/src/ObservedTurnServer.ts +72 -0
  94. package/src/Observer.ts +164 -64
  95. package/src/ObserverSummary.ts +15 -0
  96. package/src/common/utils.ts +12 -2
  97. package/src/index.ts +5 -0
  98. package/src/schema/ClientEventTypes.ts +112 -0
  99. package/src/schema/{metaTypes.ts → ClientMetaTypes.ts} +1 -1
  100. package/src/updaters/ObserverUpdater.ts +5 -0
  101. package/src/updaters/OnAllCallObserverUpdater_.ts +46 -0
  102. package/src/updaters/OnAllClientCallUpdater.ts +46 -0
  103. package/src/updaters/OnAnyCallObserverUpdater_.ts +32 -0
  104. package/src/updaters/OnAnyClientCallUpdater.ts +32 -0
  105. package/src/updaters/OnIntervalUpdater.ts +19 -0
  106. package/src/updaters/Updater.ts +5 -0
  107. package/tsconfig.json +1 -1
  108. package/lib/schema/eventTypes.d.ts +0 -33
  109. package/lib/schema/eventTypes.d.ts.map +0 -1
  110. package/lib/schema/eventTypes.js +0 -38
  111. package/lib/schema/metaTypes.d.ts.map +0 -1
  112. package/lib/schema/metaTypes.js +0 -16
  113. package/lib/utils/CallUpdater.d.ts.map +0 -1
  114. package/lib/utils/OnAllClientCallUpdater.d.ts +0 -16
  115. package/lib/utils/OnAllClientCallUpdater.d.ts.map +0 -1
  116. package/lib/utils/OnAllClientCallUpdater.js +0 -58
  117. package/lib/utils/onAnyClientCallUpdater.d.ts +0 -14
  118. package/lib/utils/onAnyClientCallUpdater.d.ts.map +0 -1
  119. package/lib/utils/onAnyClientCallUpdater.js +0 -51
  120. package/src/schema/eventTypes.ts +0 -36
  121. package/src/utils/OnAllClientCallUpdater.ts +0 -68
  122. package/src/utils/onAnyClientCallUpdater.ts +0 -59
  123. /package/lib/{utils/CallUpdater.js → ObservedCallSummary.js} +0 -0
  124. /package/lib/{utils → updaters}/CallUpdater.d.ts +0 -0
  125. /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,7 @@ 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
+ 'update': [],
74
76
  close: [];
75
77
  };
76
78
 
@@ -106,11 +108,15 @@ export class ObservedPeerConnection extends EventEmitter {
106
108
  public closedAt?: number;
107
109
  public updated = Date.now();
108
110
 
111
+ public availableIncomingBitrate = 0;
112
+ public availableOutgoingBitrate = 0;
109
113
  public totalInboundPacketsLost = 0;
110
114
  public totalInboundPacketsReceived = 0;
111
115
  public totalOutboundPacketsSent = 0;
112
116
  public totalDataChannelBytesSent = 0;
113
117
  public totalDataChannelBytesReceived = 0;
118
+ public totalDataChannelMessagesSent = 0;
119
+ public totalDataChannelMessagesReceived = 0;
114
120
 
115
121
  public totalSentAudioBytes = 0;
116
122
  public totalSentVideoBytes = 0;
@@ -126,6 +132,8 @@ export class ObservedPeerConnection extends EventEmitter {
126
132
  public deltaOutboundPacketsSent = 0;
127
133
  public deltaDataChannelBytesSent = 0;
128
134
  public deltaDataChannelBytesReceived = 0;
135
+ public deltaDataChannelMessagesSent = 0;
136
+ public deltaDataChannelMessagesReceived = 0;
129
137
  public deltaInboundReceivedBytes = 0;
130
138
  public deltaOutboundSentBytes = 0;
131
139
 
@@ -135,6 +143,8 @@ export class ObservedPeerConnection extends EventEmitter {
135
143
  public deltaReceivedVideoPackets = 0;
136
144
  public deltaSentAudioBytes = 0;
137
145
  public deltaSentVideoBytes = 0;
146
+ public deltaTransportSentBytes = 0;
147
+ public deltaTransportReceivedBytes = 0;
138
148
 
139
149
  public receivingPacketsPerSecond = 0;
140
150
  public sendingPacketsPerSecond = 0;
@@ -143,12 +153,13 @@ export class ObservedPeerConnection extends EventEmitter {
143
153
  public receivingAudioBitrate = 0;
144
154
  public receivingVideoBitrate = 0;
145
155
 
146
- public avgRttInMs?: number;
147
- public avgJitter?: number;
156
+ public currentRttInMs?: number;
157
+ public currentJitter?: number;
148
158
 
149
159
  public usingTCP = false;
150
160
  public usingTURN = false;
151
161
 
162
+ public observedTurnServer?: ObservedTurnServer;
152
163
  public readonly observedCertificates = new Map<string, ObservedCertificate>();
153
164
  public readonly observedCodecs = new Map<string, ObservedCodec>();
154
165
  public readonly observedDataChannels = new Map<string, ObservedDataChannel>();
@@ -239,6 +250,14 @@ export class ObservedPeerConnection extends EventEmitter {
239
250
  .filter((pair) => pair !== undefined) as ObservedIceCandidatePair[];
240
251
  }
241
252
 
253
+ public get selectedIceCandiadtePairForTurn() {
254
+ return this.selectedIceCandidatePairs
255
+ .filter((pair) =>
256
+ pair.getLocalCandidate()?.candidateType === 'relay' &&
257
+ pair.getRemoteCandidate()?.url?.startsWith('turn:')
258
+ );
259
+ }
260
+
242
261
  public close() {
243
262
  if (this.closed) return;
244
263
  this.closed = true;
@@ -259,6 +278,10 @@ export class ObservedPeerConnection extends EventEmitter {
259
278
  this.observedRemoteInboundRtps.clear();
260
279
  this.observedRemoteOutboundRtps.clear();
261
280
 
281
+ this.client.call.observer.observedTURN.removePeerConnection(this);
282
+
283
+ if (!this.closedAt) this.closedAt = Date.now();
284
+
262
285
  this.emit('close');
263
286
  }
264
287
 
@@ -266,6 +289,8 @@ export class ObservedPeerConnection extends EventEmitter {
266
289
  if (this.closed) return;
267
290
  this._visited = true;
268
291
 
292
+ this.availableIncomingBitrate = 0;
293
+ this.availableOutgoingBitrate = 0;
269
294
  this.deltaInboundPacketsLost = 0;
270
295
  this.deltaInboundPacketsReceived = 0;
271
296
  this.deltaOutboundPacketsSent = 0;
@@ -279,6 +304,9 @@ export class ObservedPeerConnection extends EventEmitter {
279
304
  this.deltaReceivedVideoPackets = 0;
280
305
  this.deltaSentAudioBytes = 0;
281
306
  this.deltaSentVideoBytes = 0;
307
+ this.deltaTransportReceivedBytes = 0;
308
+ this.deltaTransportSentBytes = 0;
309
+
282
310
  this.sendingAudioBitrate = 0;
283
311
  this.sendingVideoBitrate = 0;
284
312
  this.receivingAudioBitrate = 0;
@@ -287,6 +315,8 @@ export class ObservedPeerConnection extends EventEmitter {
287
315
  const now = Date.now();
288
316
  const elapsedTimeInMs = now - this.updated;
289
317
  const elapsedTimeInSec = elapsedTimeInMs / 1000;
318
+ const rttMeasurementsInSec: number[] = [];
319
+ const jitterMeasurements: number[] = [];
290
320
 
291
321
  if (sample.certificates) {
292
322
  for (const certificate of sample.certificates) {
@@ -300,7 +330,14 @@ export class ObservedPeerConnection extends EventEmitter {
300
330
  }
301
331
  if (sample.dataChannels) {
302
332
  for (const dataChannel of sample.dataChannels) {
303
- this._updateDataChannelStats(dataChannel);
333
+ const observedDataChannel = this._updateDataChannelStats(dataChannel);
334
+
335
+ if (!observedDataChannel) continue;
336
+
337
+ this.deltaDataChannelBytesSent += observedDataChannel.deltaBytesSent;
338
+ this.deltaDataChannelBytesReceived += observedDataChannel.deltaBytesReceived;
339
+ this.deltaDataChannelMessagesSent += observedDataChannel.deltaMessagesSent;
340
+ this.deltaDataChannelMessagesReceived += observedDataChannel.deltaMessagesReceived;
304
341
  }
305
342
  }
306
343
  if (sample.iceCandidates) {
@@ -310,12 +347,29 @@ export class ObservedPeerConnection extends EventEmitter {
310
347
  }
311
348
  if (sample.iceCandidatePairs) {
312
349
  for (const iceCandidatePair of sample.iceCandidatePairs) {
313
- this._updateIceCandidatePairStats(iceCandidatePair);
350
+ const observedCandidatePair = this._updateIceCandidatePairStats(iceCandidatePair);
351
+
352
+ if (!observedCandidatePair) continue;
353
+
354
+ if (observedCandidatePair.currentRoundTripTime) {
355
+ rttMeasurementsInSec.push(observedCandidatePair.currentRoundTripTime);
356
+ }
357
+ if (observedCandidatePair.availableIncomingBitrate) {
358
+ this.availableIncomingBitrate += observedCandidatePair.availableIncomingBitrate;
359
+ }
360
+ if (observedCandidatePair.availableOutgoingBitrate) {
361
+ this.availableOutgoingBitrate += observedCandidatePair.availableOutgoingBitrate;
362
+ }
314
363
  }
315
364
  }
316
365
  if (sample.iceTransports) {
317
366
  for (const iceTransport of sample.iceTransports) {
318
- this._updateIceTransportStats(iceTransport);
367
+ const observedIceTransport = this._updateIceTransportStats(iceTransport);
368
+
369
+ if (!observedIceTransport) return;
370
+
371
+ observedIceTransport.bytesReceived;
372
+
319
373
  }
320
374
  }
321
375
  if (sample.inboundRtps) {
@@ -338,6 +392,10 @@ export class ObservedPeerConnection extends EventEmitter {
338
392
  this.deltaReceivedVideoPackets += observedInboundRtp.deltaReceivedPackets;
339
393
  break;
340
394
  }
395
+
396
+ if (observedInboundRtp.jitter) {
397
+ jitterMeasurements.push(observedInboundRtp.jitter);
398
+ }
341
399
  }
342
400
  }
343
401
  if (sample.mediaPlayouts) {
@@ -374,12 +432,21 @@ export class ObservedPeerConnection extends EventEmitter {
374
432
  }
375
433
  if (sample.peerConnectionTransports) {
376
434
  for (const peerConnectionTransport of sample.peerConnectionTransports) {
377
- this._updatePeerConnectionTransportStats(peerConnectionTransport);
435
+ const observedTransport = this._updatePeerConnectionTransportStats(peerConnectionTransport);
436
+
437
+ if (!observedTransport) continue;
438
+
378
439
  }
379
440
  }
380
441
  if (sample.remoteInboundRtps) {
381
442
  for (const remoteInboundRtp of sample.remoteInboundRtps) {
382
- this._updateRemoteInboundRtpStats(remoteInboundRtp);
443
+ const observedRemoteInboundRtp = this._updateRemoteInboundRtpStats(remoteInboundRtp);
444
+
445
+ if (!observedRemoteInboundRtp) continue;
446
+
447
+ if (observedRemoteInboundRtp.roundTripTime) {
448
+ rttMeasurementsInSec.push(observedRemoteInboundRtp.roundTripTime);
449
+ }
383
450
  }
384
451
  }
385
452
  if (sample.remoteOutboundRtps) {
@@ -408,6 +475,8 @@ export class ObservedPeerConnection extends EventEmitter {
408
475
  this.totalOutboundPacketsSent += this.deltaOutboundPacketsSent;
409
476
  this.totalDataChannelBytesSent += this.deltaDataChannelBytesSent;
410
477
  this.totalDataChannelBytesReceived += this.deltaDataChannelBytesReceived;
478
+ this.totalDataChannelMessagesSent += this.deltaDataChannelMessagesSent;
479
+ this.totalDataChannelMessagesReceived += this.deltaDataChannelMessagesReceived;
411
480
  this.totalReceivedAudioBytes += this.deltaReceivedAudioBytes;
412
481
  this.totalReceivedVideoBytes += this.deltaReceivedVideoBytes;
413
482
  this.totalSentAudioBytes += this.deltaSentAudioBytes;
@@ -419,20 +488,55 @@ export class ObservedPeerConnection extends EventEmitter {
419
488
 
420
489
  this.receivingPacketsPerSecond = this.deltaInboundPacketsReceived / elapsedTimeInSec;
421
490
  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
-
491
+ this.sendingAudioBitrate = (this.deltaSentAudioBytes * 8) / elapsedTimeInSec;
492
+ this.sendingVideoBitrate = (this.deltaSentVideoBytes * 8) / elapsedTimeInSec;
493
+ this.receivingAudioBitrate = (this.deltaReceivedAudioBytes * 8) / elapsedTimeInSec;
494
+ this.receivingVideoBitrate = (this.deltaReceivedVideoBytes * 8) / elapsedTimeInSec;
495
+
496
+ if (rttMeasurementsInSec.length > 0) {
497
+ this.currentRttInMs = getMedian(rttMeasurementsInSec, false) * 1000;
498
+ } else {
499
+ this.currentRttInMs = undefined;
500
+ }
501
+ if (jitterMeasurements.length > 0) {
502
+ this.currentJitter = getMedian(jitterMeasurements, false);
503
+ } else {
504
+ this.currentJitter = undefined;
505
+ }
506
+ const wasUsingTURN = this.usingTURN;
427
507
  const selectedIceCandidatePairs = this.selectedIceCandidatePairs;
508
+ const selectedCandidatePairForTurn: ObservedIceCandidatePair[] = [];
428
509
 
429
- this.usingTCP = selectedIceCandidatePairs.some((pair) => pair.getLocalCandidate()?.protocol === 'tcp');
430
- this.usingTURN = selectedIceCandidatePairs.some((pair) => pair.getLocalCandidate()?.candidateType === 'relay') &&
431
- selectedIceCandidatePairs.some((pair) => pair.getRemoteCandidate()?.url?.startsWith('turn:'));
510
+ this.usingTCP = false;
511
+ this.usingTURN = false;
432
512
 
513
+ for (const selectedCandidatePair of selectedIceCandidatePairs) {
514
+ if (selectedCandidatePair.getLocalCandidate()?.protocol === 'tcp') {
515
+ this.usingTCP = true;
516
+ }
517
+ if (selectedCandidatePair.getLocalCandidate()?.candidateType === 'relay' && selectedCandidatePair.getRemoteCandidate()?.url?.startsWith('turn:')) {
518
+ selectedCandidatePairForTurn.push(selectedCandidatePair);
519
+ this.usingTURN = true;
520
+ }
521
+ this.deltaTransportReceivedBytes += selectedCandidatePair.deltaBytesReceived;
522
+ this.deltaTransportSentBytes += selectedCandidatePair.deltaBytesSent;
523
+ }
524
+
525
+ if (this.usingTURN) {
526
+ if (!this.observedTurnServer) {
527
+ this.observedTurnServer = this.client.call.observer.observedTURN.addPeerConnection(this);
528
+ }
529
+ this.observedTurnServer?.updateTurnUsage(...selectedCandidatePairForTurn);
530
+ } else if (wasUsingTURN) {
531
+ if (!this.usingTURN) {
532
+ this.client.call.observer.observedTURN.removePeerConnection(this);
533
+ }
534
+ }
433
535
  this.calculatedScore.value = sample.score;
434
536
  this.updated = now;
435
537
  this._checkVisited();
538
+
539
+ this.emit('update');
436
540
  }
437
541
 
438
542
  private _checkVisited() {
@@ -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
+ }
@@ -0,0 +1,72 @@
1
+ import { ObservedIceCandidatePair } from './ObservedIceCandidatePair';
2
+ import { ObservedPeerConnection } from './ObservedPeerConnection';
3
+ import { ObservedTURN } from './ObservedTURN';
4
+
5
+ export class ObservedTurnServer {
6
+ public totalBytesSent = 0;
7
+ public totalBytesReceived = 0;
8
+ public totalPacketsSent = 0;
9
+ public totalPacketsReceived = 0;
10
+
11
+ public packetsSentPerSecond = 0;
12
+ public packetsReceivedPerSecond = 0;
13
+ public outboundBitrate = 0;
14
+ public inboundBitrate = 0;
15
+
16
+ public deltaBytesSent = 0;
17
+ public deltaBytesReceived = 0;
18
+ public deltaPacketsSent = 0;
19
+ public deltaPacketsReceived = 0;
20
+
21
+ public readonly observedPeerConnections = new Map<string, ObservedPeerConnection>();
22
+
23
+ public updated = Date.now();
24
+
25
+ public constructor(
26
+ public readonly url: string,
27
+ public readonly observedTURN: ObservedTURN,
28
+ ) {
29
+
30
+ }
31
+
32
+ public updateTurnUsage(...selectedcandidatepairs: ObservedIceCandidatePair[]) {
33
+ for (const selectedcandidatepair of selectedcandidatepairs) {
34
+ this.deltaBytesReceived += selectedcandidatepair.deltaBytesReceived;
35
+ this.deltaBytesSent += selectedcandidatepair.deltaBytesSent;
36
+ this.deltaPacketsReceived += selectedcandidatepair.deltaPacketsReceived;
37
+ this.deltaPacketsSent += selectedcandidatepair.deltaPacketsSent;
38
+ }
39
+ }
40
+
41
+ public update() {
42
+ const now = Date.now();
43
+ const deltaInS = (now - this.updated) / 1000;
44
+
45
+ this.packetsSentPerSecond = this.deltaPacketsSent / deltaInS;
46
+ this.packetsReceivedPerSecond = this.deltaPacketsReceived / deltaInS;
47
+ this.outboundBitrate = (this.deltaBytesReceived * 8) / deltaInS;
48
+ this.inboundBitrate = (this.deltaBytesSent * 8) / deltaInS;
49
+
50
+ this.totalBytesSent += this.deltaBytesSent;
51
+ this.totalBytesReceived += this.deltaBytesReceived;
52
+ this.totalPacketsSent += this.deltaPacketsSent;
53
+ this.totalPacketsReceived += this.deltaPacketsReceived;
54
+
55
+ this.observedTURN.totalBytesSent += this.deltaBytesSent;
56
+ this.observedTURN.totalBytesReceived += this.deltaBytesReceived;
57
+ this.observedTURN.totalPacketsSent += this.deltaPacketsSent;
58
+ this.observedTURN.totalPacketsReceived += this.deltaPacketsReceived;
59
+
60
+ this.observedTURN.inboundBitrate += this.inboundBitrate;
61
+ this.observedTURN.outboundBitrate += this.outboundBitrate;
62
+ this.observedTURN.packetsReceivedPerSecond += this.packetsReceivedPerSecond;
63
+ this.observedTURN.packetsSentPerSecond += this.packetsSentPerSecond;
64
+
65
+ this.deltaBytesSent = 0;
66
+ this.deltaBytesReceived = 0;
67
+ this.deltaPacketsSent = 0;
68
+ this.deltaPacketsReceived = 0;
69
+
70
+ this.updated = now;
71
+ }
72
+ }