Bladeren bron

Merge pull request #49 from jitsi/reduce-muc-joined-time

Reduce MUC joined time
dev1
hristoterezov 9 jaren geleden
bovenliggende
commit
c57caa5ac7
3 gewijzigde bestanden met toevoegingen van 186 en 150 verwijderingen
  1. 32
    25
      modules/xmpp/ChatRoom.js
  2. 33
    39
      modules/xmpp/SDP.js
  3. 121
    86
      modules/xmpp/moderator.js

+ 32
- 25
modules/xmpp/ChatRoom.js Bestand weergeven

@@ -123,12 +123,13 @@ ChatRoom.prototype.join = function (password) {
123 123
 };
124 124
 
125 125
 ChatRoom.prototype.sendPresence = function (fromJoin) {
126
-    if (!this.presMap['to'] || (!this.joined && !fromJoin)) {
126
+    var to = this.presMap['to'];
127
+    if (!to || (!this.joined && !fromJoin)) {
127 128
         // Too early to send presence - not initialized
128 129
         return;
129 130
     }
130 131
 
131
-    var pres = $pres({to: this.presMap['to'] });
132
+    var pres = $pres({to: to });
132 133
     pres.c('x', {xmlns: this.presMap['xns']});
133 134
 
134 135
     if (this.password) {
@@ -138,13 +139,22 @@ ChatRoom.prototype.sendPresence = function (fromJoin) {
138 139
     pres.up();
139 140
 
140 141
     // Send XEP-0115 'c' stanza that contains our capabilities info
141
-    if (this.connection.caps) {
142
-        this.connection.caps.node = this.xmpp.options.clientNode;
143
-        pres.c('c', this.connection.caps.generateCapsAttrs()).up();
142
+    var connection = this.connection;
143
+    var caps = connection.caps;
144
+    if (caps) {
145
+        caps.node = this.xmpp.options.clientNode;
146
+        pres.c('c', caps.generateCapsAttrs()).up();
144 147
     }
145 148
 
146 149
     parser.JSON2packet(this.presMap.nodes, pres);
147
-    this.connection.send(pres);
150
+    connection.send(pres);
151
+    if (fromJoin) {
152
+        // XXX We're pressed for time here because we're beginning a complex
153
+        // and/or lengthy conference-establishment process which supposedly
154
+        // involves multiple RTTs. We don't have the time to wait for Strophe to
155
+        // decide to send our IQ.
156
+        connection.flush();
157
+    }
148 158
 };
149 159
 
150 160
 
@@ -214,17 +224,16 @@ ChatRoom.prototype.onPresence = function (pres) {
214 224
     var member = {};
215 225
     member.show = $(pres).find('>show').text();
216 226
     member.status = $(pres).find('>status').text();
217
-    var tmp = $(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>item');
218
-    member.affiliation = tmp.attr('affiliation');
219
-    member.role = tmp.attr('role');
227
+    var mucUserItem
228
+        = $(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>item');
229
+    member.affiliation = mucUserItem.attr('affiliation');
230
+    member.role = mucUserItem.attr('role');
220 231
 
221 232
     // Focus recognition
222
-    member.jid = tmp.attr('jid');
223
-    member.isFocus = false;
224
-    if (member.jid
225
-        && member.jid.indexOf(this.moderator.getFocusUserJid() + "/") === 0) {
226
-        member.isFocus = true;
227
-    }
233
+    var jid = mucUserItem.attr('jid');
234
+    member.jid = jid;
235
+    member.isFocus
236
+        = !!jid && jid.indexOf(this.moderator.getFocusUserJid() + "/") === 0;
228 237
 
229 238
     $(pres).find(">x").remove();
230 239
     var nodes = [];
@@ -248,11 +257,9 @@ ChatRoom.prototype.onPresence = function (pres) {
248 257
     }
249 258
 
250 259
     if (from == this.myroomjid) {
251
-        if (member.affiliation == 'owner'
252
-            &&  this.role !== member.role) {
253
-                this.role = member.role;
254
-                this.eventEmitter.emit(
255
-                    XMPPEvents.LOCAL_ROLE_CHANGED, this.role);
260
+        if (member.affiliation == 'owner' && this.role !== member.role) {
261
+            this.role = member.role;
262
+            this.eventEmitter.emit(XMPPEvents.LOCAL_ROLE_CHANGED, this.role);
256 263
         }
257 264
         if (!this.joined) {
258 265
             this.joined = true;
@@ -272,7 +279,7 @@ ChatRoom.prototype.onPresence = function (pres) {
272 279
                 if(this.lastJibri)
273 280
                     this.recording.handleJibriPresence(this.lastJibri);
274 281
             }
275
-            logger.info("Ignore focus: " + from + ", real JID: " + member.jid);
282
+            logger.info("Ignore focus: " + from + ", real JID: " + jid);
276 283
         }
277 284
         else {
278 285
             this.eventEmitter.emit(
@@ -281,15 +288,16 @@ ChatRoom.prototype.onPresence = function (pres) {
281 288
     } else {
282 289
         // Presence update for existing participant
283 290
         // Watch role change:
284
-        if (this.members[from].role != member.role) {
285
-            this.members[from].role = member.role;
291
+        var memberOfThis = this.members[from];
292
+        if (memberOfThis.role != member.role) {
293
+            memberOfThis.role = member.role;
286 294
             this.eventEmitter.emit(
287 295
                 XMPPEvents.MUC_ROLE_CHANGED, from, member.role);
288 296
         }
289 297
 
290 298
         // store the new display name
291 299
         if(member.displayName)
292
-            this.members[from].displayName = member.displayName;
300
+            memberOfThis.displayName = member.displayName;
293 301
     }
294 302
 
295 303
     // after we had fired member or room joined events, lets fire events
@@ -343,7 +351,6 @@ ChatRoom.prototype.onPresence = function (pres) {
343 351
         if(this.recording)
344 352
             this.recording.handleJibriPresence(jibri);
345 353
     }
346
-
347 354
 };
348 355
 
349 356
 ChatRoom.prototype.processNode = function (node, from) {

+ 33
- 39
modules/xmpp/SDP.js Bestand weergeven

@@ -5,29 +5,33 @@ var SDPUtil = require("./SDPUtil");
5 5
 
6 6
 // SDP STUFF
7 7
 function SDP(sdp) {
8
-    /**
9
-     * Whether or not to remove TCP ice candidates when translating from/to jingle.
10
-     * @type {boolean}
11
-     */
12
-    this.removeTcpCandidates = false;
13
-
14
-    /**
15
-     * Whether or not to remove UDP ice candidates when translating from/to jingle.
16
-     * @type {boolean}
17
-     */
18
-    this.removeUdpCandidates = false;
19
-
20
-    this.media = sdp.split('\r\nm=');
21
-    for (var i = 1; i < this.media.length; i++) {
22
-        this.media[i] = 'm=' + this.media[i];
23
-        if (i != this.media.length - 1) {
24
-            this.media[i] += '\r\n';
8
+    var media = sdp.split('\r\nm=');
9
+    for (var i = 1, length = media.length; i < length; i++) {
10
+        var media_i = 'm=' + media[i];
11
+        if (i != length - 1) {
12
+            media_i += '\r\n';
25 13
         }
14
+        media[i] = media_i;
26 15
     }
27
-    this.session = this.media.shift() + '\r\n';
28
-    this.raw = this.session + this.media.join('');
16
+    var session = media.shift() + '\r\n';
17
+
18
+    this.media = media;
19
+    this.raw = session + media.join('');
20
+    this.session = session;
29 21
 }
30 22
 
23
+/**
24
+ * Whether or not to remove TCP ice candidates when translating from/to jingle.
25
+ * @type {boolean}
26
+ */
27
+SDP.prototype.removeTcpCandidates = false;
28
+
29
+/**
30
+ * Whether or not to remove UDP ice candidates when translating from/to jingle.
31
+ * @type {boolean}
32
+ */
33
+SDP.prototype.removeUdpCandidates = false;
34
+
31 35
 /**
32 36
  * Returns map of MediaChannel mapped per channel idx.
33 37
  */
@@ -57,7 +61,7 @@ SDP.prototype.getMediaSsrcMap = function() {
57 61
             media.ssrcs[linessrc].lines.push(line);
58 62
         });
59 63
         tmp = SDPUtil.find_lines(self.media[mediaindex], 'a=ssrc-group:');
60
-        tmp.forEach(function(line){
64
+        tmp.forEach(function(line) {
61 65
             var idx = line.indexOf(' ');
62 66
             var semantics = line.substr(0, idx).substr(13);
63 67
             var ssrcs = line.substr(14 + semantics.length).split(' ');
@@ -107,13 +111,10 @@ SDP.prototype.mangle = function () {
107 111
                 if (rtpmap.name == 'CN' || rtpmap.name == 'ISAC')
108 112
                     continue;
109 113
                 mline.fmt.push(rtpmap.id);
110
-                newdesc += lines[j] + '\r\n';
111
-            } else {
112
-                newdesc += lines[j] + '\r\n';
113 114
             }
115
+            newdesc += lines[j] + '\r\n';
114 116
         }
115
-        this.media[i] = SDPUtil.build_mline(mline) + '\r\n';
116
-        this.media[i] += newdesc;
117
+        this.media[i] = SDPUtil.build_mline(mline) + '\r\n' + newdesc;
117 118
     }
118 119
     this.raw = this.session + this.media.join('');
119 120
 };
@@ -162,8 +163,7 @@ SDP.prototype.toJingle = function (elem, thecreator) {
162 163
         mline = SDPUtil.parse_mline(this.media[i].split('\r\n')[0]);
163 164
         if (!(mline.media === 'audio' ||
164 165
               mline.media === 'video' ||
165
-              mline.media === 'application'))
166
-        {
166
+              mline.media === 'application')) {
167 167
             continue;
168 168
         }
169 169
         var assrcline = SDPUtil.find_line(this.media[i], 'a=ssrc:');
@@ -247,16 +247,12 @@ SDP.prototype.toJingle = function (elem, thecreator) {
247 247
                     elem.attrs({name: "cname", value:Math.random().toString(36).substring(7)});
248 248
                     elem.up();
249 249
                     var msid = null;
250
-                    if(mline.media == "audio")
251
-                    {
250
+                    if(mline.media == "audio") {
252 251
                         msid = APP.RTC.localAudio._getId();
253
-                    }
254
-                    else
255
-                    {
252
+                    } else {
256 253
                         msid = APP.RTC.localVideo._getId();
257 254
                     }
258
-                    if(msid != null)
259
-                    {
255
+                    if(msid != null) {
260 256
                         msid = SDPUtil.filter_special_chars(msid);
261 257
                         elem.c('parameter');
262 258
                         elem.attrs({name: "msid", value:msid});
@@ -497,11 +493,9 @@ SDP.prototype.jingle2media = function (content) {
497 493
         // estos hack to reject an m-line.
498 494
         tmp.port = '0';
499 495
     }
500
-    if (content.find('>transport>fingerprint').length || desc.find('encryption').length) {
501
-        if (sctp.length)
502
-            tmp.proto = 'DTLS/SCTP';
503
-        else
504
-            tmp.proto = 'RTP/SAVPF';
496
+    if (content.find('>transport>fingerprint').length
497
+            || desc.find('encryption').length) {
498
+        tmp.proto = sctp.length ? 'DTLS/SCTP' : 'RTP/SAVPF';
505 499
     } else {
506 500
         tmp.proto = 'RTP/AVPF';
507 501
     }

+ 121
- 86
modules/xmpp/moderator.js Bestand weergeven

@@ -246,103 +246,138 @@ Moderator.prototype.parseConfigOptions =  function (resultIq) {
246 246
     logger.info("Sip gateway enabled:  " + this.sipGatewayEnabled);
247 247
 };
248 248
 
249
-// FIXME =  we need to show the fact that we're waiting for the focus
250
-// to the user(or that focus is not available)
249
+// FIXME We need to show the fact that we're waiting for the focus to the user
250
+// (or that the focus is not available)
251
+/**
252
+ * Allocates the conference focus.
253
+ *
254
+ * @param {Function} callback - the function to be called back upon the
255
+ * successful allocation of the conference focus
256
+ */
251 257
 Moderator.prototype.allocateConferenceFocus =  function (callback) {
252 258
     // Try to use focus user JID from the config
253 259
     this.setFocusUserJid(this.xmppService.options.focusUserJid);
254 260
     // Send create conference IQ
255
-    var iq = this.createConferenceIq();
256 261
     var self = this;
257 262
     this.connection.sendIQ(
258
-        iq,
263
+        this.createConferenceIq(),
259 264
         function (result) {
260
-
261
-            // Setup config options
262
-            self.parseConfigOptions(result);
263
-
264
-            if ('true' === $(result).find('conference').attr('ready')) {
265
-                // Reset both timers
266
-                self.getNextTimeout(true);
267
-                self.getNextErrorTimeout(true);
268
-                // Exec callback
269
-                callback();
270
-            } else {
271
-                var waitMs = self.getNextTimeout();
272
-                logger.info("Waiting for the focus... " + waitMs);
273
-                // Reset error timeout
274
-                self.getNextErrorTimeout(true);
275
-                window.setTimeout(
276
-                    function () {
277
-                        self.allocateConferenceFocus(callback);
278
-                    }, waitMs);
279
-            }
265
+            self._allocateConferenceFocusSuccess(result, callback);
280 266
         },
281 267
         function (error) {
282
-            // Invalid session ? remove and try again
283
-            // without session ID to get a new one
284
-            var invalidSession
285
-                = $(error).find('>error>session-invalid').length;
286
-            if (invalidSession) {
287
-                logger.info("Session expired! - removing");
288
-                self.settings.clearSessionId();
289
-            }
290
-            if ($(error).find('>error>graceful-shutdown').length) {
291
-                self.eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);
292
-                return;
293
-            }
294
-            // Check for error returned by the reservation system
295
-            var reservationErr = $(error).find('>error>reservation-error');
296
-            if (reservationErr.length) {
297
-                // Trigger error event
298
-                var errorCode = reservationErr.attr('error-code');
299
-                var errorMsg;
300
-                if ($(error).find('>error>text')) {
301
-                    errorMsg = $(error).find('>error>text').text();
302
-                }
303
-                self.eventEmitter.emit(
304
-                    XMPPEvents.RESERVATION_ERROR, errorCode, errorMsg);
305
-                return;
306
-            }
307
-            // Not authorized to create new room
308
-            if ($(error).find('>error>not-authorized').length) {
309
-                logger.warn("Unauthorized to start the conference", error);
310
-                var toDomain
311
-                    = Strophe.getDomainFromJid(error.getAttribute('to'));
312
-                if (toDomain !==
313
-                    self.xmppService.options.hosts.anonymousdomain) {
314
-                    //FIXME:  "is external" should come either from
315
-                    // the focus or config.js
316
-                    self.externalAuthEnabled = true;
317
-                }
318
-                self.eventEmitter.emit(
319
-                    XMPPEvents.AUTHENTICATION_REQUIRED,
320
-                    function () {
321
-                        self.allocateConferenceFocus(
322
-                            callback);
323
-                    });
324
-                return;
325
-            }
326
-            var waitMs = self.getNextErrorTimeout();
327
-            logger.error("Focus error, retry after " + waitMs, error);
328
-            // Show message
329
-            var focusComponent = self.getFocusComponent();
330
-            var retrySec = waitMs / 1000;
331
-            //FIXME:  message is duplicated ?
332
-            // Do not show in case of session invalid
333
-            // which means just a retry
334
-            if (!invalidSession) {
335
-                self.eventEmitter.emit(XMPPEvents.FOCUS_DISCONNECTED,
336
-                    focusComponent, retrySec);
337
-            }
338
-            // Reset response timeout
339
-            self.getNextTimeout(true);
340
-            window.setTimeout(
268
+            self._allocateConferenceFocusError(error);
269
+        });
270
+    // XXX We're pressed for time here because we're beginning a complex and/or
271
+    // lengthy conference-establishment process which supposedly involves
272
+    // multiple RTTs. We don't have the time to wait for Strophe to decide to
273
+    // send our IQ.
274
+    this.connection.flush();
275
+};
276
+
277
+/**
278
+ * Invoked by {@link #allocateConferenceFocus} upon its request receiving an
279
+ * error result.
280
+ *
281
+ * @param error - the error result of the request that
282
+ * {@link #allocateConferenceFocus} sent
283
+ * @param {Function} callback - the function to be called back upon the
284
+ * successful allocation of the conference focus
285
+ */
286
+Moderator.prototype._allocateConferenceFocusError = function (error, callback) {
287
+    var self = this;
288
+
289
+    // If the session is invalid, remove and try again without session ID to get
290
+    // a new one
291
+    var invalidSession = $(error).find('>error>session-invalid').length;
292
+    if (invalidSession) {
293
+        logger.info("Session expired! - removing");
294
+        self.settings.clearSessionId();
295
+    }
296
+    if ($(error).find('>error>graceful-shutdown').length) {
297
+        self.eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);
298
+        return;
299
+    }
300
+    // Check for error returned by the reservation system
301
+    var reservationErr = $(error).find('>error>reservation-error');
302
+    if (reservationErr.length) {
303
+        // Trigger error event
304
+        var errorCode = reservationErr.attr('error-code');
305
+        var errorTextNode = $(error).find('>error>text');
306
+        var errorMsg;
307
+        if (errorTextNode) {
308
+            errorMsg = errorTextNode.text();
309
+        }
310
+        self.eventEmitter.emit(
311
+                XMPPEvents.RESERVATION_ERROR, errorCode, errorMsg);
312
+        return;
313
+    }
314
+    // Not authorized to create new room
315
+    if ($(error).find('>error>not-authorized').length) {
316
+        logger.warn("Unauthorized to start the conference", error);
317
+        var toDomain = Strophe.getDomainFromJid(error.getAttribute('to'));
318
+        if (toDomain !== self.xmppService.options.hosts.anonymousdomain) {
319
+            //FIXME "is external" should come either from the focus or config.js
320
+            self.externalAuthEnabled = true;
321
+        }
322
+        self.eventEmitter.emit(
323
+                XMPPEvents.AUTHENTICATION_REQUIRED,
341 324
                 function () {
342 325
                     self.allocateConferenceFocus(callback);
343
-                }, waitMs);
344
-        }
345
-    );
326
+                });
327
+        return;
328
+    }
329
+    var waitMs = self.getNextErrorTimeout();
330
+    logger.error("Focus error, retry after " + waitMs, error);
331
+    // Show message
332
+    var focusComponent = self.getFocusComponent();
333
+    var retrySec = waitMs / 1000;
334
+    //FIXME: message is duplicated ? Do not show in case of session invalid
335
+    // which means just a retry
336
+    if (!invalidSession) {
337
+        self.eventEmitter.emit(
338
+                XMPPEvents.FOCUS_DISCONNECTED, focusComponent, retrySec);
339
+    }
340
+    // Reset response timeout
341
+    self.getNextTimeout(true);
342
+    window.setTimeout(
343
+            function () {
344
+                self.allocateConferenceFocus(callback);
345
+            },
346
+            waitMs);
347
+};
348
+
349
+/**
350
+ * Invoked by {@link #allocateConferenceFocus} upon its request receiving a
351
+ * success (i.e. non-error) result.
352
+ *
353
+ * @param result - the success (i.e. non-error) result of the request that
354
+ * {@link #allocateConferenceFocus} sent
355
+ * @param {Function} callback - the function to be called back upon the
356
+ * successful allocation of the conference focus
357
+ */
358
+Moderator.prototype._allocateConferenceFocusSuccess = function (
359
+        result,
360
+        callback) {
361
+    // Setup config options
362
+    this.parseConfigOptions(result);
363
+
364
+    // Reset the error timeout (because we haven't failed here).
365
+    this.getNextErrorTimeout(true);
366
+    if ('true' === $(result).find('conference').attr('ready')) {
367
+        // Reset the non-error timeout (because we've succeeded here).
368
+        this.getNextTimeout(true);
369
+        // Exec callback
370
+        callback();
371
+    } else {
372
+        var waitMs = this.getNextTimeout();
373
+        logger.info("Waiting for the focus... " + waitMs);
374
+        var self = this;
375
+        window.setTimeout(
376
+                function () {
377
+                    self.allocateConferenceFocus(callback);
378
+                },
379
+                waitMs);
380
+    }
346 381
 };
347 382
 
348 383
 Moderator.prototype.authenticate = function () {

Laden…
Annuleren
Opslaan