Explorar el Código

Reconnection fixes.

- Reconnection failed if original connection was never established
- When the `credentials_url` is specified, keep on trying to reconnect.
JC Brand hace 8 años
padre
commit
bfde4d3e4c
Se han modificado 2 ficheros con 55 adiciones y 59 borrados
  1. 5 0
      docs/CHANGES.md
  2. 50 59
      src/converse-core.js

+ 5 - 0
docs/CHANGES.md

@@ -10,6 +10,11 @@
   collection has its `browserStorage` configured.
   Causes `Error: A "url" property or function must be specified`. [jcbrand]
 - Don't open the controlbox on contact requests. [jcbrand]
+- Bugfix: Reconnection fails when original connection was never established. [jcbrand]
+- If a `credentials_url` is provided, then keep on attempting to reconnect when connection is down.  [jcbrand]
+- Remove (undocumented) `callback` config parameter for `converse.initialize`.
+  Instead, `converse.initialize` returns a promise which will resolve once
+  initialization is complete. [jcbrand]
 
 ## 2.0.1 (2016-11-07)
 - #203 New configuration setting [muc_domain](https://conversejs.org/docs/html/configuration.html#muc_domain) [jcbrand]

+ 50 - 59
src/converse-core.js

@@ -396,11 +396,7 @@
             converse.connection.disconnect('re-connecting');
             converse.connection.reset();
             converse._tearDown();
-            if (converse.authentication !== "prebind") {
-                converse.autoLogin();
-            } else if (converse.prebind_url) {
-                converse.startNewBOSHSession();
-            }
+            converse.logIn(null, true);
         }, 1000);
 
         this.onDisconnected = function (condition) {
@@ -440,7 +436,7 @@
                 delete converse.disconnection_cause;
                 if (converse.connection.reconnecting) {
                     converse.log(status === Strophe.Status.CONNECTED ? 'Reconnected' : 'Reattached');
-                    converse.onReconnected();
+                    converse.onConnected(true);
                 } else {
                     converse.log(status === Strophe.Status.CONNECTED ? 'Connected' : 'Attached');
                     if (converse.connection.restored) {
@@ -666,19 +662,33 @@
             }
         };
 
-        this.onStatusInitialized = function () {
-            converse.registerIntervalHandler();
-            converse.initRoster();
+        this.onStatusInitialized = function (reconnecting) {
+            /* Continue with session establishment (e.g. fetching chat boxes,
+             * populating the roster etc.) necessary once the connection has
+             * been established.
+             */
+            if (reconnecting) {
+                // No need to recreate the roster, otherwise we lose our
+                // cached data. However we still emit an event, to give
+                // event handlers a chance to register views for the
+                // roster and its groups, before we start populating.
+                converse.emit('rosterReadyAfterReconnection');
+            } else {
+                converse.registerIntervalHandler();
+                converse.initRoster();
+            }
+            // First set up chat boxes, before populating the roster, so that
+            // the controlbox is properly set up and ready for the rosterview.
             converse.chatboxes.onConnected();
             converse.populateRoster();
             converse.registerPresenceHandler();
             converse.giveFeedback(__('Contacts'));
-            if (typeof converse.callback === 'function') {
-                // XXX: Deprecate in favor of init_deferred
-                converse.callback();
+            if (reconnecting) {
+                converse.xmppstatus.sendPresence();
+            } else {
+                init_deferred.resolve();
+                converse.emit('initialized');
             }
-            init_deferred.resolve();
-            converse.emit('initialized');
         };
 
         this.setUserJid = function () {
@@ -688,52 +698,33 @@
             converse.domain = Strophe.getDomainFromJid(converse.connection.jid);
         };
 
-        this.onConnected = function (callback) {
+        this.onConnected = function (reconnecting) {
             /* Called as soon as a new connection has been established, either
              * by logging in or by attaching to an existing BOSH session.
              */
-            // XXX: ran into an issue where a returned PubSub BOSH response was
-            // not received by the browser. The solution was to flush the
-            // connection early on. I don't know what the underlying cause of
-            // this issue is, and whether it's a Strophe.js or Prosody bug.
-            // My suspicion is that Prosody replies to an invalid/expired
-            // Request, which is why the browser then doesn't receive it.
-            // In any case, flushing here (sending out a new BOSH request)
-            // solves the problem.
+            // Solves problem of returned PubSub BOSH response not received
+            // by browser.
             converse.connection.flush();
-            // When reconnecting, there might be some open chat boxes. We don't
-            // know whether these boxes are of the same account or not, so we
-            // close them now.
-            converse.chatboxviews.closeAllChatBoxes();
+
             converse.setUserJid();
-            converse.features = new converse.Features();
             converse.enableCarbons();
-            converse.initStatus().done(converse.onStatusInitialized);
-            converse.emit('connected');
-            converse.emit('ready'); // BBB: Will be removed.
-        };
 
-        this.onReconnected = function () {
-            /* Called when converse has succesfully reconnected to the XMPP
-             * server after the session was dropped.
-             * Similar to the `onConnected` method, but skips a few unnecessary
-             * steps.
-             */
-            converse.setUserJid();
-            converse.registerPresenceHandler();
-            converse.chatboxes.registerMessageHandler();
-            if (_.isUndefined(converse.roster)) {
-                converse.initRoster();
+            // If there's no xmppstatus obj, then we were never connected to
+            // begin with, so we set reconnecting to false.
+            reconnecting = _.isUndefined(converse.xmppstatus) ? false : reconnecting;
+
+            if (reconnecting) {
+                converse.onStatusInitialized(true);
+                converse.emit('reconnected');
             } else {
-                // Give event handlers a chance to register views for the
-                // roster and its groups, before we start populating.
-                converse.emit('rosterReadyAfterReconnection');
+                // There might be some open chat boxes. We don't
+                // know whether these boxes are of the same account or not, so we
+                // close them now.
+                converse.chatboxviews.closeAllChatBoxes();
+                converse.features = new converse.Features();
+                converse.initStatus().done(_.partial(converse.onStatusInitialized, false));
+                converse.emit('connected');
             }
-            converse.chatboxes.onConnected();
-            converse.populateRoster();
-            converse.xmppstatus.sendPresence();
-            converse.emit('reconnected');
-            converse.giveFeedback(__('Contacts'));
         };
 
         this.RosterContact = Backbone.Model.extend({
@@ -1777,10 +1768,10 @@
             });
         };
 
-        this.attemptPreboundSession = function (tokens) {
+        this.attemptPreboundSession = function (reconnecting) {
             /* Handle session resumption or initialization when prebind is being used.
              */
-            if (this.keepalive) {
+            if (!reconnecting && this.keepalive) {
                 if (!this.jid) {
                     throw new Error("attemptPreboundSession: when using 'keepalive' with 'prebind, "+
                                     "you must supply the JID of the current user.");
@@ -1794,7 +1785,7 @@
             }
 
             // No keepalive, or session resumption has failed.
-            if (this.jid && this.sid && this.rid) {
+            if (!reconnecting && this.jid && this.sid && this.rid) {
                 return this.connection.attach(this.jid, this.sid, this.rid, this.onConnectStatusChanged);
             } else if (this.prebind_url) {
                 return this.startNewBOSHSession();
@@ -1841,14 +1832,14 @@
             }
         };
 
-        this.attemptNonPreboundSession = function (credentials) {
+        this.attemptNonPreboundSession = function (credentials, reconnecting) {
             /* Handle session resumption or initialization when prebind is not being used.
              *
              * Two potential options exist and are handled in this method:
              *  1. keepalive
              *  2. auto_login
              */
-            if (this.keepalive) {
+            if (this.keepalive && !reconnecting) {
                 try {
                     return this.connection.restore(this.jid, this.onConnectStatusChanged);
                 } catch (e) {
@@ -1877,13 +1868,13 @@
             }
         };
 
-        this.logIn = function (credentials) {
+        this.logIn = function (credentials, reconnecting) {
             // We now try to resume or automatically set up a new session.
             // Otherwise the user will be shown a login form.
             if (this.authentication === converse.PREBIND) {
-                this.attemptPreboundSession();
+                this.attemptPreboundSession(reconnecting);
             } else {
-                this.attemptNonPreboundSession(credentials);
+                this.attemptNonPreboundSession(credentials, reconnecting);
             }
         };