Reconnection fixes.

- Reconnection failed if original connection was never established
- When the `credentials_url` is specified, keep on trying to reconnect.
This commit is contained in:
JC Brand 2016-11-23 11:53:06 +00:00
parent e90632d6fd
commit bfde4d3e4c
2 changed files with 56 additions and 60 deletions

View File

@ -10,6 +10,11 @@
collection has its `browserStorage` configured. collection has its `browserStorage` configured.
Causes `Error: A "url" property or function must be specified`. [jcbrand] Causes `Error: A "url" property or function must be specified`. [jcbrand]
- Don't open the controlbox on contact requests. [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) ## 2.0.1 (2016-11-07)
- #203 New configuration setting [muc_domain](https://conversejs.org/docs/html/configuration.html#muc_domain) [jcbrand] - #203 New configuration setting [muc_domain](https://conversejs.org/docs/html/configuration.html#muc_domain) [jcbrand]

View File

@ -396,11 +396,7 @@
converse.connection.disconnect('re-connecting'); converse.connection.disconnect('re-connecting');
converse.connection.reset(); converse.connection.reset();
converse._tearDown(); converse._tearDown();
if (converse.authentication !== "prebind") { converse.logIn(null, true);
converse.autoLogin();
} else if (converse.prebind_url) {
converse.startNewBOSHSession();
}
}, 1000); }, 1000);
this.onDisconnected = function (condition) { this.onDisconnected = function (condition) {
@ -440,7 +436,7 @@
delete converse.disconnection_cause; delete converse.disconnection_cause;
if (converse.connection.reconnecting) { if (converse.connection.reconnecting) {
converse.log(status === Strophe.Status.CONNECTED ? 'Reconnected' : 'Reattached'); converse.log(status === Strophe.Status.CONNECTED ? 'Reconnected' : 'Reattached');
converse.onReconnected(); converse.onConnected(true);
} else { } else {
converse.log(status === Strophe.Status.CONNECTED ? 'Connected' : 'Attached'); converse.log(status === Strophe.Status.CONNECTED ? 'Connected' : 'Attached');
if (converse.connection.restored) { if (converse.connection.restored) {
@ -666,19 +662,33 @@
} }
}; };
this.onStatusInitialized = function () { this.onStatusInitialized = function (reconnecting) {
converse.registerIntervalHandler(); /* Continue with session establishment (e.g. fetching chat boxes,
converse.initRoster(); * 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.chatboxes.onConnected();
converse.populateRoster(); converse.populateRoster();
converse.registerPresenceHandler(); converse.registerPresenceHandler();
converse.giveFeedback(__('Contacts')); converse.giveFeedback(__('Contacts'));
if (typeof converse.callback === 'function') { if (reconnecting) {
// XXX: Deprecate in favor of init_deferred converse.xmppstatus.sendPresence();
converse.callback(); } else {
init_deferred.resolve();
converse.emit('initialized');
} }
init_deferred.resolve();
converse.emit('initialized');
}; };
this.setUserJid = function () { this.setUserJid = function () {
@ -688,52 +698,33 @@
converse.domain = Strophe.getDomainFromJid(converse.connection.jid); 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 /* Called as soon as a new connection has been established, either
* by logging in or by attaching to an existing BOSH session. * by logging in or by attaching to an existing BOSH session.
*/ */
// XXX: ran into an issue where a returned PubSub BOSH response was // Solves problem of returned PubSub BOSH response not received
// not received by the browser. The solution was to flush the // by browser.
// 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.
converse.connection.flush(); 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.setUserJid();
converse.registerPresenceHandler(); converse.enableCarbons();
converse.chatboxes.registerMessageHandler();
if (_.isUndefined(converse.roster)) { // If there's no xmppstatus obj, then we were never connected to
converse.initRoster(); // begin with, so we set reconnecting to false.
reconnecting = _.isUndefined(converse.xmppstatus) ? false : reconnecting;
if (reconnecting) {
converse.onStatusInitialized(true);
converse.emit('reconnected');
} else { } else {
// Give event handlers a chance to register views for the // There might be some open chat boxes. We don't
// roster and its groups, before we start populating. // know whether these boxes are of the same account or not, so we
converse.emit('rosterReadyAfterReconnection'); // 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({ 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. /* Handle session resumption or initialization when prebind is being used.
*/ */
if (this.keepalive) { if (!reconnecting && this.keepalive) {
if (!this.jid) { if (!this.jid) {
throw new Error("attemptPreboundSession: when using 'keepalive' with 'prebind, "+ throw new Error("attemptPreboundSession: when using 'keepalive' with 'prebind, "+
"you must supply the JID of the current user."); "you must supply the JID of the current user.");
@ -1794,7 +1785,7 @@
} }
// No keepalive, or session resumption has failed. // 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); return this.connection.attach(this.jid, this.sid, this.rid, this.onConnectStatusChanged);
} else if (this.prebind_url) { } else if (this.prebind_url) {
return this.startNewBOSHSession(); 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. /* Handle session resumption or initialization when prebind is not being used.
* *
* Two potential options exist and are handled in this method: * Two potential options exist and are handled in this method:
* 1. keepalive * 1. keepalive
* 2. auto_login * 2. auto_login
*/ */
if (this.keepalive) { if (this.keepalive && !reconnecting) {
try { try {
return this.connection.restore(this.jid, this.onConnectStatusChanged); return this.connection.restore(this.jid, this.onConnectStatusChanged);
} catch (e) { } 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. // We now try to resume or automatically set up a new session.
// Otherwise the user will be shown a login form. // Otherwise the user will be shown a login form.
if (this.authentication === converse.PREBIND) { if (this.authentication === converse.PREBIND) {
this.attemptPreboundSession(); this.attemptPreboundSession(reconnecting);
} else { } else {
this.attemptNonPreboundSession(credentials); this.attemptNonPreboundSession(credentials, reconnecting);
} }
}; };