Kaynağa Gözat

Merge pull request #539 from jitsi/feat-local-remote-relayed

Treats local/remote relayed addresses differently.
dev1
George Politis 8 yıl önce
ebeveyn
işleme
ff22221a15

+ 33
- 2
JitsiConference.js Dosyayı Görüntüle

@@ -2091,15 +2091,30 @@ JitsiConference.prototype._addRemoteTracks = function(logName, remoteTracks) {
2091 2091
  */
2092 2092
 JitsiConference.prototype._onIceConnectionEstablished
2093 2093
 = function(jingleSession) {
2094
+
2095
+    if (this.p2pJingleSession !== null) {
2096
+        // store the establishment time of the p2p session as a field of the
2097
+        // JitsiConference because the p2pJingleSession might get disposed (thus
2098
+        // the value is lost).
2099
+        this.p2pEstablishmentDuration
2100
+            = this.p2pJingleSession.establishmentDuration;
2101
+    }
2102
+
2103
+    if (this.jvbJingleSession !== null) {
2104
+        this.jvbEstablishmentDuration
2105
+            = this.jvbJingleSession.establishmentDuration;
2106
+    }
2107
+
2108
+    let done = false;
2094 2109
     const forceJVB121Ratio = this.options.config.forceJVB121Ratio;
2095 2110
 
2096 2111
     // We don't care about the JVB case, there's nothing to be done
2097 2112
     if (!jingleSession.isP2P) {
2098
-        return;
2113
+        done = true;
2099 2114
     } else if (this.p2pJingleSession !== jingleSession) {
2100 2115
         logger.error('CONNECTION_ESTABLISHED - wrong P2P session instance ?!');
2101 2116
 
2102
-        return;
2117
+        done = true;
2103 2118
     } else if (!jingleSession.isInitiator
2104 2119
         && typeof forceJVB121Ratio === 'number'
2105 2120
         && Math.random() < forceJVB121Ratio) {
@@ -2107,6 +2122,22 @@ JitsiConference.prototype._onIceConnectionEstablished
2107 2122
         Statistics.analytics.addPermanentProperties({ forceJvb121: true });
2108 2123
         this._stopP2PSession('decline', 'force JVB121');
2109 2124
 
2125
+        done = true;
2126
+    }
2127
+
2128
+    if (!isNaN(this.p2pEstablishmentDuration)
2129
+        && !isNaN(this.jvbEstablishmentDuration)) {
2130
+        const establishmentDurationDiff
2131
+            = this.p2pEstablishmentDuration - this.jvbEstablishmentDuration;
2132
+
2133
+        Statistics.analytics.sendEvent({
2134
+            'name': 'ice.establishmentDurationDiff',
2135
+            'value': establishmentDurationDiff
2136
+        });
2137
+    }
2138
+
2139
+    if (done) {
2140
+
2110 2141
         return;
2111 2142
     }
2112 2143
 

+ 99
- 59
modules/statistics/AvgRTPStatsReporter.js Dosyayı Görüntüle

@@ -17,8 +17,10 @@ import * as VideoType from '../../service/RTC/VideoType';
17 17
  *
18 18
  * {
19 19
  *   p2p: true,
20
- *   conferenceSize: 1,
21
- *   relayed: true,
20
+ *   conferenceSize: 2,
21
+ *   localCandidateType: "relay",
22
+ *   remoteCandidateType: "relay",
23
+ *   transportType: "udp",
22 24
  *
23 25
  *   "stat_avg_rtt": {
24 26
  *     value: 200,
@@ -92,18 +94,12 @@ class AverageStatReport {
92 94
      * Appends the report to the analytics "data" object. The object will be
93 95
      * set under <tt>prefix</tt> + {@link this.name} key.
94 96
      * @param {Object} report the analytics "data" object
95
-     * @param {Object} extra properties to append to the analytics "data" object
96 97
      */
97
-    appendReport(report, props) {
98
-
99
-        const reportValue = {
98
+    appendReport(report) {
99
+        report[this.name] = {
100 100
             value: this.calculate(),
101 101
             samples: this.samples
102 102
         };
103
-
104
-        Object.assign(reportValue, props);
105
-
106
-        report[this.name] = reportValue;
107 103
     }
108 104
 
109 105
     /**
@@ -125,12 +121,12 @@ class AverageStatReport {
125 121
 class ConnectionAvgStats {
126 122
     /**
127 123
      * Creates new <tt>ConnectionAvgStats</tt>
128
-     * @param {JitsiConference} conference
124
+     * @param {AvgRTPStatsReporter} avgRtpStatsReporter
129 125
      * @param {boolean} isP2P
130 126
      * @param {number} n the number of samples, before arithmetic mean is to be
131 127
      * calculated and values submitted to the analytics module.
132 128
      */
133
-    constructor(conference, isP2P, n) {
129
+    constructor(avgRtpStatsReporter, isP2P, n) {
134 130
         /**
135 131
          * Is this instance for JVB or P2P connection ?
136 132
          * @type {boolean}
@@ -175,13 +171,26 @@ class ConnectionAvgStats {
175 171
          * @type {JitsiConference}
176 172
          * @private
177 173
          */
178
-        this._conference = conference;
174
+        this._avgRtpStatsReporter = avgRtpStatsReporter;
175
+
176
+        /**
177
+         * The latest average E2E RTT for the JVB connection only.
178
+         *
179
+         * This is used only when {@link ConnectionAvgStats.isP2P} equals to
180
+         * <tt>false</tt>.
181
+         *
182
+         * @type {number}
183
+         */
184
+        this._avgEnd2EndRTT = undefined;
179 185
 
180 186
         this._onConnectionStats = (tpc, stats) => {
181 187
             if (this.isP2P === tpc.isP2P) {
182 188
                 this._calculateAvgStats(stats);
183 189
             }
184 190
         };
191
+
192
+        const conference = avgRtpStatsReporter._conference;
193
+
185 194
         conference.statistics.addConnectionStatsListener(
186 195
             this._onConnectionStats);
187 196
 
@@ -219,30 +228,51 @@ class ConnectionAvgStats {
219 228
 
220 229
         if (this._sampleIdx >= this._n) {
221 230
             if (RTCBrowserType.supportsRTTStatistics()) {
222
-                const batchReport = { };
223
-                const props = {
224
-                    relayed: data.relayed,
231
+                const conference = this._avgRtpStatsReporter._conference;
232
+
233
+                const batchReport = {
225 234
                     p2p: this.isP2P,
226
-                    size: this._conference.getParticipantCount()
235
+                    size: conference.getParticipantCount()
227 236
                 };
228 237
 
229
-                this._avgRTT.appendReport(batchReport, props);
238
+                if (data.transport && data.transport.length) {
239
+                    Object.assign(batchReport, {
240
+                        localCandidateType:
241
+                            data.transport[0].localCandidateType,
242
+                        remoteCandidateType:
243
+                            data.transport[0].remoteCandidateType,
244
+                        transportType: data.transport[0].type
245
+                    });
246
+                }
230 247
 
231
-                // Report end to end RTT only for JVB
232
-                if (!this.isP2P) {
233
-                    const avgRemoteRTT = this._calculateAvgRemoteRTT();
234
-                    const avgLocalRTT = this._avgRTT.calculate();
248
+                this._avgRTT.appendReport(batchReport);
235 249
 
236
-                    if (!isNaN(avgLocalRTT) && !isNaN(avgRemoteRTT)) {
237
-                        // eslint-disable-next-line camelcase
238
-                        const reportValue = {
239
-                            value: avgLocalRTT + avgRemoteRTT
250
+                if (this.isP2P) {
251
+                    // Report RTT diff only for P2P.
252
+                    const jvbEnd2EndRTT = this
253
+                        ._avgRtpStatsReporter.jvbStatsMonitor._avgEnd2EndRTT;
254
+
255
+                    if (!isNaN(jvbEnd2EndRTT)) {
256
+                        const avgRTTDiff
257
+                            = this._avgRTT.calculate() - jvbEnd2EndRTT;
258
+
259
+                        // eslint-disable-next-line dot-notation
260
+                        batchReport['stat_avg_rtt_diff'] = {
261
+                            value: avgRTTDiff
240 262
                         };
263
+                    }
264
+                } else {
265
+                    // Report end to end RTT only for JVB.
266
+                    const avgRemoteRTT = this._calculateAvgRemoteRTT();
267
+                    const avgLocalRTT = this._avgRTT.calculate();
241 268
 
242
-                        Object.assign(reportValue, props);
269
+                    this._avgEnd2EndRTT = avgLocalRTT + avgRemoteRTT;
243 270
 
271
+                    if (!isNaN(avgLocalRTT) && !isNaN(avgRemoteRTT)) {
244 272
                         // eslint-disable-next-line dot-notation
245
-                        batchReport['stat_avg_end2endrtt'] = reportValue;
273
+                        batchReport['stat_avg_end2endrtt'] = {
274
+                            value: this._avgEnd2EndRTT
275
+                        };
246 276
                     }
247 277
                 }
248 278
 
@@ -317,13 +347,16 @@ class ConnectionAvgStats {
317 347
      *
318 348
      */
319 349
     dispose() {
320
-        this._conference.statistics.removeConnectionStatsListener(
350
+
351
+        const conference = this._avgRtpStatsReporter._conference;
352
+
353
+        conference.statistics.removeConnectionStatsListener(
321 354
             this._onConnectionStats);
322 355
         if (!this.isP2P) {
323
-            this._conference.off(
356
+            conference.off(
324 357
                 ConnectionQualityEvents.REMOTE_STATS_UPDATED,
325 358
                 this._onRemoteStatsUpdated);
326
-            this._conference.off(
359
+            conference.off(
327 360
                 ConferenceEvents.USER_LEFT,
328 361
                 this._onUserLeft);
329 362
         }
@@ -519,10 +552,10 @@ export default class AvgRTPStatsReporter {
519 552
             this._onJvb121StatusChanged);
520 553
 
521 554
         this.jvbStatsMonitor
522
-            = new ConnectionAvgStats(conference, false /* JVB */, n);
555
+            = new ConnectionAvgStats(this, false /* JVB */, n);
523 556
 
524 557
         this.p2pStatsMonitor
525
-            = new ConnectionAvgStats(conference, true /* P2P */, n);
558
+            = new ConnectionAvgStats(this, true /* P2P */, n);
526 559
     }
527 560
 
528 561
     /**
@@ -533,13 +566,14 @@ export default class AvgRTPStatsReporter {
533 566
      */
534 567
     _calculateAvgStats(data) {
535 568
 
569
+        if (!data) {
570
+            logger.error('No stats');
571
+
572
+            return;
573
+        }
574
+
536 575
         const isP2P = this._conference.isP2PActive();
537 576
         const confSize = this._conference.getParticipantCount();
538
-        const props = {
539
-            relayed: data.relayed,
540
-            p2p: isP2P,
541
-            size: confSize
542
-        };
543 577
 
544 578
         if (!isP2P && confSize < 2) {
545 579
 
@@ -556,12 +590,6 @@ export default class AvgRTPStatsReporter {
556 590
             }
557 591
         } */
558 592
 
559
-        if (!data) {
560
-            logger.error('No stats');
561
-
562
-            return;
563
-        }
564
-
565 593
         const bitrate = data.bitrate;
566 594
         const bandwidth = data.bandwidth;
567 595
         const packetLoss = data.packetLoss;
@@ -621,32 +649,44 @@ export default class AvgRTPStatsReporter {
621 649
         this._sampleIdx += 1;
622 650
 
623 651
         if (this._sampleIdx >= this._n) {
624
-            const batchReport = { };
625 652
 
626
-            this._avgAudioBitrateUp.appendReport(batchReport, props);
627
-            this._avgAudioBitrateDown.appendReport(batchReport, props);
653
+            const batchReport = {
654
+                p2p: isP2P,
655
+                size: confSize
656
+            };
657
+
658
+            if (data.transport && data.transport.length) {
659
+                Object.assign(batchReport, {
660
+                    localCandidateType: data.transport[0].localCandidateType,
661
+                    remoteCandidateType: data.transport[0].remoteCandidateType,
662
+                    transportType: data.transport[0].type
663
+                });
664
+            }
665
+
666
+            this._avgAudioBitrateUp.appendReport(batchReport);
667
+            this._avgAudioBitrateDown.appendReport(batchReport);
628 668
 
629
-            this._avgVideoBitrateUp.appendReport(batchReport, props);
630
-            this._avgVideoBitrateDown.appendReport(batchReport, props);
669
+            this._avgVideoBitrateUp.appendReport(batchReport);
670
+            this._avgVideoBitrateDown.appendReport(batchReport);
631 671
 
632 672
             if (RTCBrowserType.supportsBandwidthStatistics()) {
633
-                this._avgBandwidthUp.appendReport(batchReport, props);
634
-                this._avgBandwidthDown.appendReport(batchReport, props);
673
+                this._avgBandwidthUp.appendReport(batchReport);
674
+                this._avgBandwidthDown.appendReport(batchReport);
635 675
             }
636
-            this._avgPacketLossUp.appendReport(batchReport, props);
637
-            this._avgPacketLossDown.appendReport(batchReport, props);
638
-            this._avgPacketLossTotal.appendReport(batchReport, props);
676
+            this._avgPacketLossUp.appendReport(batchReport);
677
+            this._avgPacketLossDown.appendReport(batchReport);
678
+            this._avgPacketLossTotal.appendReport(batchReport);
639 679
 
640
-            this._avgRemoteFPS.appendReport(batchReport, props);
680
+            this._avgRemoteFPS.appendReport(batchReport);
641 681
             if (!isNaN(this._avgRemoteScreenFPS.calculate())) {
642
-                this._avgRemoteScreenFPS.appendReport(batchReport, props);
682
+                this._avgRemoteScreenFPS.appendReport(batchReport);
643 683
             }
644
-            this._avgLocalFPS.appendReport(batchReport, props);
684
+            this._avgLocalFPS.appendReport(batchReport);
645 685
             if (!isNaN(this._avgLocalScreenFPS.calculate())) {
646
-                this._avgLocalScreenFPS.appendReport(batchReport, props);
686
+                this._avgLocalScreenFPS.appendReport(batchReport);
647 687
             }
648 688
 
649
-            this._avgCQ.appendReport(batchReport, props);
689
+            this._avgCQ.appendReport(batchReport);
650 690
 
651 691
             Statistics.analytics.sendEvent(AVG_RTP_STATS_EVENT, batchReport);
652 692
 

+ 17
- 36
modules/statistics/RTPStatsCollector.js Dosyayı Görüntüle

@@ -46,7 +46,9 @@ KEYS_BY_BROWSER_TYPE[RTCBrowserType.RTC_BROWSER_CHROME] = {
46 46
     'googFrameRateSent': 'googFrameRateSent',
47 47
     'audioInputLevel': 'audioInputLevel',
48 48
     'audioOutputLevel': 'audioOutputLevel',
49
-    'currentRoundTripTime': 'googRtt'
49
+    'currentRoundTripTime': 'googRtt',
50
+    'remoteCandidateType': 'googRemoteCandidateType',
51
+    'localCandidateType': 'googLocalCandidateType'
50 52
 };
51 53
 KEYS_BY_BROWSER_TYPE[RTCBrowserType.RTC_BROWSER_EDGE] = {
52 54
     'sendBandwidth': 'googAvailableSendBandwidth',
@@ -453,33 +455,6 @@ StatsCollector.prototype.getNonNegativeStat = function(report, name) {
453 455
     return Math.max(0, value);
454 456
 };
455 457
 
456
-/**
457
- * Determines whether the local ICE candidate address is a relayed one.
458
- *
459
- * @param {TraceablePeerConnection} rtcPeerConnection the peer connection that
460
- * has the local ICE candidate address.
461
- * @param {Array} localAddressArray an array in the form
462
- * [ ip address, port ].
463
- * @return {boolean} true if the local ICE candidate is a relayed one, otherwise
464
- * false.
465
- */
466
-function isRelayed(rtcPeerConnection, localAddressArray) {
467
-    const localSdpLines
468
-        = rtcPeerConnection.localDescription.sdp.match(/[^\r\n]+/g);
469
-
470
-    for (const idx in localSdpLines) {
471
-        if (localSdpLines[idx].indexOf(localAddressArray[0])
472
-            && localSdpLines[idx].indexOf(localAddressArray[1])) {
473
-            return localSdpLines[idx].indexOf('relay') !== -1;
474
-        }
475
-    }
476
-
477
-    logger
478
-        .warn('The candidate address was not found in the local description.');
479
-
480
-    return false;
481
-}
482
-
483 458
 /* eslint-disable no-continue */
484 459
 
485 460
 /**
@@ -517,15 +492,20 @@ StatsCollector.prototype.processStatsReport = function() {
517 492
         } catch (e) { /* not supported*/ }
518 493
 
519 494
         if (now.type === 'googCandidatePair') {
520
-            let active, ip, localip, rtt, type;
521
-            let relayed = false;
495
+            let active, ip, localCandidateType, localip,
496
+                remoteCandidateType, rtt, type;
522 497
 
523 498
             try {
499
+                active = getStatValue(now, 'activeConnection');
500
+                if (!active) {
501
+                    continue;
502
+                }
503
+
524 504
                 ip = getStatValue(now, 'remoteAddress');
525 505
                 type = getStatValue(now, 'transportType');
526 506
                 localip = getStatValue(now, 'localAddress');
527
-                relayed = isRelayed(this.peerconnection, localip.split(':'));
528
-                active = getStatValue(now, 'activeConnection');
507
+                localCandidateType = getStatValue(now, 'localCandidateType');
508
+                remoteCandidateType = getStatValue(now, 'remoteCandidateType');
529 509
                 rtt = this.getNonNegativeStat(now, 'currentRoundTripTime');
530 510
             } catch (e) { /* not supported*/ }
531 511
             if (!ip || !type || !localip || active !== 'true') {
@@ -545,7 +525,8 @@ StatsCollector.prototype.processStatsReport = function() {
545 525
                     type,
546 526
                     localip,
547 527
                     p2p: this.peerconnection.isP2P,
548
-                    relayed,
528
+                    localCandidateType,
529
+                    remoteCandidateType,
549 530
                     rtt
550 531
                 });
551 532
             }
@@ -565,9 +546,9 @@ StatsCollector.prototype.processStatsReport = function() {
565 546
                 ip: `${remote.ipAddress}:${remote.portNumber}`,
566 547
                 type: local.transport,
567 548
                 localip: `${local.ipAddress}:${local.portNumber}`,
568
-                relayed: isRelayed(
569
-                    this.peerconnection, [ local.ipAddress, local.portNumber ]),
570
-                p2p: this.peerconnection.isP2P
549
+                p2p: this.peerconnection.isP2P,
550
+                localCandidateType: local.candidateType,
551
+                remoteCandidateType: remote.candidateType
571 552
             });
572 553
         }
573 554
 

+ 12
- 1
modules/xmpp/JingleSessionPC.js Dosyayı Görüntüle

@@ -199,6 +199,14 @@ export default class JingleSessionPC extends JingleSession {
199 199
          * @type {boolean}
200 200
          */
201 201
         this.wasConnected = false;
202
+
203
+        /**
204
+         * Keeps track of how long (in ms) it took from ICE start to ICE
205
+         * connect.
206
+         *
207
+         * @type {number}
208
+         */
209
+        this.establishmentDuration = undefined;
202 210
     }
203 211
 
204 212
     /* eslint-enable max-params */
@@ -381,10 +389,12 @@ export default class JingleSessionPC extends JingleSession {
381 389
                             this._iceCheckingStartedTimestamp,
382 390
                             this._gatheringStartedTimestamp);
383 391
 
392
+                    this.establishmentDuration = now - iceStarted;
393
+
384 394
                     Statistics.analytics.sendEvent(
385 395
                         `${eventName}establishmentDuration`,
386 396
                         {
387
-                            value: now - iceStarted
397
+                            value: this.establishmentDuration
388 398
                         });
389 399
                     this.wasConnected = true;
390 400
                     this.room.eventEmitter.emit(
@@ -1187,6 +1197,7 @@ export default class JingleSessionPC extends JingleSession {
1187 1197
      */
1188 1198
     onTerminated(reasonCondition, reasonText) {
1189 1199
         this.state = JingleSessionState.ENDED;
1200
+        this.establishmentDuration = undefined;
1190 1201
 
1191 1202
         // Do something with reason and reasonCondition when we start to care
1192 1203
         // this.reasonCondition = reasonCondition;

Loading…
İptal
Kaydet