Parcourir la source

JiConOp2 (#1569)

* squash: Extracts parsing disco info in utility method.

* squash: Extracts parsing disco info identities and features in utility method.

* squash: Skip disco-info on reconnection.

Doing disco info queries only once.
If the call is longer than 24-hours turn credentials may be expired.

* feat: Adds handler for early messages with conference info data.

* feat: JiConOp handling for shard name.

* squash: Drops unneeded check.

* squash: Changes message type to service-info.

* squash: Moves utility parseDiscoInfo out of the Caps class.
tags/v0.0.2
Дамян Минков il y a 4 ans
Parent
révision
ab667ef809
Aucun compte lié à l'adresse e-mail de l'auteur
2 fichiers modifiés avec 101 ajouts et 53 suppressions
  1. 25
    18
      modules/xmpp/Caps.js
  2. 76
    35
      modules/xmpp/xmpp.js

+ 25
- 18
modules/xmpp/Caps.js Voir le fichier

@@ -50,6 +50,30 @@ function generateSha(identities, features) {
50 50
     return b64_sha1(sortedIdentities + sortedFeatures);
51 51
 }
52 52
 
53
+/**
54
+ * Parses the disco-info node and returns the sets of features and identities.
55
+ * @param {String} node The node with results to parse.
56
+ * @returns {{features: Set<any>, identities: Set<any>}}
57
+ */
58
+export function parseDiscoInfo(node) {
59
+    const features = new Set();
60
+    const identities = new Set();
61
+
62
+    $(node).find('>query>feature')
63
+        .each((_, el) => features.add(el.getAttribute('var')));
64
+    $(node).find('>query>identity')
65
+        .each((_, el) => identities.add({
66
+            type: el.getAttribute('type'),
67
+            name: el.getAttribute('name'),
68
+            category: el.getAttribute('category')
69
+        }));
70
+
71
+    return {
72
+        features,
73
+        identities
74
+    };
75
+}
76
+
53 77
 /**
54 78
  * Implements xep-0115 ( http://xmpp.org/extensions/xep-0115.html )
55 79
  */
@@ -187,24 +211,7 @@ export default class Caps extends Listenable {
187 211
     _getDiscoInfo(jid, node, timeout) {
188 212
         return new Promise((resolve, reject) =>
189 213
             this.disco.info(jid, node, response => {
190
-                const features = new Set();
191
-                const identities = new Set();
192
-
193
-                $(response)
194
-                    .find('>query>feature')
195
-                    .each(
196
-                        (_, el) => features.add(el.getAttribute('var')));
197
-                $(response)
198
-                    .find('>query>identity')
199
-                    .each(
200
-                        (_, el) => identities.add({
201
-                            type: el.getAttribute('type'),
202
-                            name: el.getAttribute('name'),
203
-                            category: el.getAttribute('category')
204
-                        }));
205
-                resolve({
206
-                    features,
207
-                    identities });
214
+                resolve(parseDiscoInfo(response));
208 215
             }, reject, timeout)
209 216
         );
210 217
     }

+ 76
- 35
modules/xmpp/xmpp.js Voir le fichier

@@ -13,7 +13,7 @@ import GlobalOnErrorHandler from '../util/GlobalOnErrorHandler';
13 13
 import Listenable from '../util/Listenable';
14 14
 import RandomUtil from '../util/RandomUtil';
15 15
 
16
-import Caps from './Caps';
16
+import Caps, { parseDiscoInfo } from './Caps';
17 17
 import XmppConnection from './XmppConnection';
18 18
 import MucConnectionPlugin from './strophe.emuc';
19 19
 import JingleConnectionPlugin from './strophe.jingle';
@@ -278,52 +278,22 @@ export default class XMPP extends Listenable {
278 278
 
279 279
         this.eventEmitter.emit(XMPPEvents.CONNECTION_STATUS_CHANGED, credentials, status, msg);
280 280
         if (status === Strophe.Status.CONNECTED || status === Strophe.Status.ATTACHED) {
281
-            this.connection.jingle.getStunAndTurnCredentials();
281
+            this.sendDiscoInfo && this.connection.jingle.getStunAndTurnCredentials();
282 282
 
283 283
             logger.info(`My Jabber ID: ${this.connection.jid}`);
284 284
 
285 285
             // XmppConnection emits CONNECTED again on reconnect - a good opportunity to clear any "last error" flags
286 286
             this._resetState();
287 287
 
288
-            // FIXME no need to do it again on stream resume
289
-            this.caps.getFeaturesAndIdentities(this.options.hosts.domain)
288
+            this.sendDiscoInfo && this.caps.getFeaturesAndIdentities(this.options.hosts.domain)
290 289
                 .then(({ features, identities }) => {
291 290
                     if (!features.has(Strophe.NS.PING)) {
292 291
                         logger.error(`Ping NOT supported by ${
293 292
                             this.options.hosts.domain} - please enable ping in your XMPP server config`);
294 293
                     }
295 294
 
296
-                    // check for speakerstats
297
-                    identities.forEach(identity => {
298
-                        if (identity.type === 'speakerstats') {
299
-                            this.speakerStatsComponentAddress = identity.name;
300
-                        }
301
-
302
-                        if (identity.type === 'conference_duration') {
303
-                            this.conferenceDurationComponentAddress = identity.name;
304
-                        }
305
-
306
-                        if (identity.type === 'lobbyrooms') {
307
-                            this.lobbySupported = true;
308
-                            identity.name && this.caps.getFeaturesAndIdentities(identity.name, identity.type)
309
-                                .then(({ features: f }) => {
310
-                                    f.forEach(fr => {
311
-                                        if (fr.endsWith('#displayname_required')) {
312
-                                            this.eventEmitter.emit(
313
-                                                JitsiConnectionEvents.DISPLAY_NAME_REQUIRED);
314
-                                        }
315
-                                    });
316
-                                })
317
-                                .catch(e => logger.warn('Error getting features from lobby.', e && e.message));
318
-                        }
319
-                    });
320
-
321
-                    if (this.speakerStatsComponentAddress
322
-                        || this.conferenceDurationComponentAddress) {
323
-                        this.connection.addHandler(
324
-                            this._onPrivateMessage.bind(this), null,
325
-                            'message', null, null);
326
-                    }
295
+                    this._processDiscoInfoIdentities(
296
+                        identities, undefined /* when querying we will query for features */);
327 297
                 })
328 298
                 .catch(error => {
329 299
                     const errmsg = 'Feature discovery error';
@@ -333,6 +303,9 @@ export default class XMPP extends Listenable {
333 303
                     logger.error(errmsg, error);
334 304
                 });
335 305
 
306
+            // make sure we don't query again
307
+            this.sendDiscoInfo = false;
308
+
336 309
             if (credentials.password) {
337 310
                 this.authenticatedUser = true;
338 311
             }
@@ -419,6 +392,50 @@ export default class XMPP extends Listenable {
419 392
         }
420 393
     }
421 394
 
395
+    /**
396
+     * Process received identities.
397
+     * @param {Set<String>} identities The identities to process.
398
+     * @param {Set<String>} features The features to process, optional. If missing lobby component will be queried
399
+     * for more features.
400
+     * @private
401
+     */
402
+    _processDiscoInfoIdentities(identities, features) {
403
+        // check for speakerstats
404
+        identities.forEach(identity => {
405
+            if (identity.type === 'speakerstats') {
406
+                this.speakerStatsComponentAddress = identity.name;
407
+            }
408
+
409
+            if (identity.type === 'conference_duration') {
410
+                this.conferenceDurationComponentAddress = identity.name;
411
+            }
412
+
413
+            if (identity.type === 'lobbyrooms') {
414
+                this.lobbySupported = true;
415
+                const processLobbyFeatures = f => {
416
+                    f.forEach(fr => {
417
+                        if (fr.endsWith('#displayname_required')) {
418
+                            this.eventEmitter.emit(JitsiConnectionEvents.DISPLAY_NAME_REQUIRED);
419
+                        }
420
+                    });
421
+                };
422
+
423
+                if (features) {
424
+                    processLobbyFeatures(features);
425
+                } else {
426
+                    identity.name && this.caps.getFeaturesAndIdentities(identity.name, identity.type)
427
+                        .then(({ features: f }) => processLobbyFeatures(f))
428
+                        .catch(e => logger.warn('Error getting features from lobby.', e && e.message));
429
+                }
430
+            }
431
+        });
432
+
433
+        if (this.speakerStatsComponentAddress
434
+            || this.conferenceDurationComponentAddress) {
435
+            this.connection.addHandler(this._onPrivateMessage.bind(this), null, 'message', null, null);
436
+        }
437
+    }
438
+
422 439
     /**
423 440
     * Parses a raw failure xmpp xml message received on auth failed.
424 441
     *
@@ -469,6 +486,30 @@ export default class XMPP extends Listenable {
469 486
         //  Status.ATTACHED - The connection has been attached
470 487
 
471 488
         this._resetState();
489
+
490
+        this.sendDiscoInfo = true;
491
+
492
+        if (this.connection._stropheConn && this.connection._stropheConn._addSysHandler) {
493
+            this.connection._stropheConn._addSysHandler(msg => {
494
+                this.sendDiscoInfo = false;
495
+
496
+                this.connection.jingle.onReceiveStunAndTurnCredentials(msg);
497
+
498
+                const { features, identities } = parseDiscoInfo(msg);
499
+
500
+                this._processDiscoInfoIdentities(identities, features);
501
+
502
+                // check for shard name in identities
503
+                identities.forEach(i => {
504
+                    if (i.type === 'shard') {
505
+                        this.options.deploymentInfo.shard = i.name;
506
+                    }
507
+                });
508
+            }, null, 'message', 'service-info', null);
509
+        } else {
510
+            logger.warn('Cannot attach strophe system handler, jiconop cannot operate');
511
+        }
512
+
472 513
         this.connection.connect(
473 514
             jid,
474 515
             password,

Chargement…
Annuler
Enregistrer