|
@@ -69,6 +69,26 @@ export default class JingleSessionPC extends JingleSession {
|
69
|
69
|
options) {
|
70
|
70
|
super(sid, me, peerjid, connection, mediaConstraints, iceConfig);
|
71
|
71
|
|
|
72
|
+ /**
|
|
73
|
+ * Stores result of {@link window.performance.now()} at the time when
|
|
74
|
+ * ICE enters 'checking' state.
|
|
75
|
+ * @type {number|null} null if no value has been stored yet
|
|
76
|
+ * @private
|
|
77
|
+ */
|
|
78
|
+ this._iceCheckingStartedTimestamp = null;
|
|
79
|
+
|
|
80
|
+ /**
|
|
81
|
+ * Stores result of {@link window.performance.now()} at the time when
|
|
82
|
+ * first ICE candidate is spawned by the peerconnection to mark when
|
|
83
|
+ * ICE gathering started. That's, because ICE gathering state changed
|
|
84
|
+ * events are not supported by most of the browsers, so we try something
|
|
85
|
+ * that will work everywhere. It may not be as accurate, but given that
|
|
86
|
+ * 'host' candidate usually comes first, the delay should be minimal.
|
|
87
|
+ * @type {number|null} null if no value has been stored yet
|
|
88
|
+ * @private
|
|
89
|
+ */
|
|
90
|
+ this._gatheringStartedTimestamp = null;
|
|
91
|
+
|
72
|
92
|
this.lasticecandidate = false;
|
73
|
93
|
this.closed = false;
|
74
|
94
|
|
|
@@ -217,8 +237,13 @@ export default class JingleSessionPC extends JingleSession {
|
217
|
237
|
|
218
|
238
|
// XXX this is broken, candidate is not parsed.
|
219
|
239
|
const candidate = ev.candidate;
|
|
240
|
+ const now = window.performance.now();
|
220
|
241
|
|
221
|
242
|
if (candidate) {
|
|
243
|
+ if (this._gatheringStartedTimestamp === null) {
|
|
244
|
+ this._gatheringStartedTimestamp = now;
|
|
245
|
+ }
|
|
246
|
+
|
222
|
247
|
// Discard candidates of disabled protocols.
|
223
|
248
|
let protocol = candidate.protocol;
|
224
|
249
|
|
|
@@ -234,6 +259,15 @@ export default class JingleSessionPC extends JingleSession {
|
234
|
259
|
}
|
235
|
260
|
}
|
236
|
261
|
}
|
|
262
|
+ } else {
|
|
263
|
+ // End of gathering
|
|
264
|
+ let eventName = this.isP2P ? 'p2p.ice.' : 'ice.';
|
|
265
|
+
|
|
266
|
+ eventName += this.isInitiator ? 'initiator' : 'responder';
|
|
267
|
+ eventName += '.gatheringDuration';
|
|
268
|
+ Statistics.analytics.sendEvent(
|
|
269
|
+ eventName,
|
|
270
|
+ { value: now - this._gatheringStartedTimestamp });
|
237
|
271
|
}
|
238
|
272
|
this.sendIceCandidate(candidate);
|
239
|
273
|
};
|
|
@@ -290,6 +324,9 @@ export default class JingleSessionPC extends JingleSession {
|
290
|
324
|
this,
|
291
|
325
|
this.peerconnection.iceConnectionState);
|
292
|
326
|
switch (this.peerconnection.iceConnectionState) {
|
|
327
|
+ case 'checking':
|
|
328
|
+ this._iceCheckingStartedTimestamp = now;
|
|
329
|
+ break;
|
293
|
330
|
case 'connected':
|
294
|
331
|
// Informs interested parties that the connection has been
|
295
|
332
|
// restored.
|
|
@@ -297,11 +334,22 @@ export default class JingleSessionPC extends JingleSession {
|
297
|
334
|
if (this.isreconnect) {
|
298
|
335
|
this.room.eventEmitter.emit(
|
299
|
336
|
XMPPEvents.CONNECTION_RESTORED, this);
|
300
|
|
- } else if (!this.wasConnected) {
|
301
|
|
- this.room.eventEmitter.emit(
|
302
|
|
- XMPPEvents.CONNECTION_ESTABLISHED, this);
|
303
|
337
|
}
|
|
338
|
+ }
|
|
339
|
+
|
|
340
|
+ if (!this.wasConnected && this.wasstable) {
|
|
341
|
+ let eventName = this.isP2P ? 'p2p.ice.' : 'ice.';
|
|
342
|
+
|
|
343
|
+ eventName += this.isInitiator ? 'initiator.' : 'responder.';
|
|
344
|
+ eventName += 'checksDuration';
|
|
345
|
+ Statistics.analytics.sendEvent(
|
|
346
|
+ eventName,
|
|
347
|
+ {
|
|
348
|
+ value: now - this._iceCheckingStartedTimestamp
|
|
349
|
+ });
|
304
|
350
|
this.wasConnected = true;
|
|
351
|
+ this.room.eventEmitter.emit(
|
|
352
|
+ XMPPEvents.CONNECTION_ESTABLISHED, this);
|
305
|
353
|
}
|
306
|
354
|
this.isreconnect = false;
|
307
|
355
|
break;
|