Implements fault tolerant connect (closes #268).

This commit is contained in:
George Politis 2015-04-22 22:31:18 +02:00
parent 8af3a65d37
commit e0cba855a6
4 changed files with 19275 additions and 18973 deletions

View File

@ -19,7 +19,7 @@
<script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib --> <script src="libs/popover.js?v=1"></script><!-- bootstrap tooltip lib -->
<script src="libs/toastr.js?v=1"></script><!-- notifications lib --> <script src="libs/toastr.js?v=1"></script><!-- notifications lib -->
<script src="interface_config.js?v=5"></script> <script src="interface_config.js?v=5"></script>
<script src="libs/app.bundle.js?v=62"></script> <script src="libs/app.bundle.js?v=63"></script>
<script src="analytics.js?v=1"></script><!-- google analytics plugin --> <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
<link rel="stylesheet" href="css/font.css?v=7"/> <link rel="stylesheet" href="css/font.css?v=7"/>
<link rel="stylesheet" href="css/toastr.css?v=1"> <link rel="stylesheet" href="css/toastr.css?v=1">

File diff suppressed because it is too large Load Diff

View File

@ -9,12 +9,21 @@ var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
var RTCEvents = require("../../service/RTC/RTCEvents"); var RTCEvents = require("../../service/RTC/RTCEvents");
var UIEvents = require("../../service/UI/UIEvents"); var UIEvents = require("../../service/UI/UIEvents");
var XMPPEvents = require("../../service/xmpp/XMPPEvents"); var XMPPEvents = require("../../service/xmpp/XMPPEvents");
var retry = require('retry');
var eventEmitter = new EventEmitter(); var eventEmitter = new EventEmitter();
var connection = null; var connection = null;
var authenticatedUser = false; var authenticatedUser = false;
function connect(jid, password) { function connect(jid, password) {
var faultTolerantConnect = retry.operation({
retries: 3
});
// fault tolerant connect
faultTolerantConnect.attempt(function () {
connection = XMPP.createConnection(); connection = XMPP.createConnection();
Moderator.setConnection(connection); Moderator.setConnection(connection);
@ -41,16 +50,41 @@ function connect(jid, password) {
connection.emuc.addDisplayNameToPresence(settings.displayName); connection.emuc.addDisplayNameToPresence(settings.displayName);
} }
// connection.connect() starts the connection process.
//
// As the connection process proceeds, the user supplied callback will
// be triggered multiple times with status updates. The callback should
// take two arguments - the status code and the error condition.
//
// The status code will be one of the values in the Strophe.Status
// constants. The error condition will be one of the conditions defined
// in RFC 3920 or the condition strophe-parsererror.
//
// The Parameters wait, hold and route are optional and only relevant
// for BOSH connections. Please see XEP 124 for a more detailed
// explanation of the optional parameters.
//
// Connection status constants for use by the connection handler
// callback.
//
// Status.ERROR - An error has occurred (websockets specific)
// Status.CONNECTING - The connection is currently being made
// Status.CONNFAIL - The connection attempt failed
// Status.AUTHENTICATING - The connection is authenticating
// Status.AUTHFAIL - The authentication attempt failed
// Status.CONNECTED - The connection has succeeded
// Status.DISCONNECTED - The connection has been terminated
// Status.DISCONNECTING - The connection is currently being terminated
// Status.ATTACHED - The connection has been attached
var anonymousConnectionFailed = false; var anonymousConnectionFailed = false;
var wasConnected = false; var connectionFailed = false;
var lastErrorMsg; var lastErrorMsg;
connection.connect(jid, password, function (status, msg) { connection.connect(jid, password, function (status, msg) {
console.log('Strophe status changed to', console.log('Strophe status changed to',
Strophe.getStatusString(status), msg); Strophe.getStatusString(status), msg);
if (status === Strophe.Status.CONNECTED) { if (status === Strophe.Status.CONNECTED) {
wasConnected = true;
if (config.useStunTurn) { if (config.useStunTurn) {
connection.jingle.getStunAndTurnCredentials(); connection.jingle.getStunAndTurnCredentials();
} }
@ -63,15 +97,49 @@ function connect(jid, password) {
} else if (status === Strophe.Status.CONNFAIL) { } else if (status === Strophe.Status.CONNFAIL) {
if (msg === 'x-strophe-bad-non-anon-jid') { if (msg === 'x-strophe-bad-non-anon-jid') {
anonymousConnectionFailed = true; anonymousConnectionFailed = true;
} else {
connectionFailed = true;
} }
lastErrorMsg = msg; lastErrorMsg = msg;
} else if (status === Strophe.Status.DISCONNECTED) { } else if (status === Strophe.Status.DISCONNECTED) {
if (anonymousConnectionFailed) { if (anonymousConnectionFailed) {
// prompt user for username and password // prompt user for username and password
XMPP.promptLogin(); XMPP.promptLogin();
} else if (!wasConnected) { } else {
eventEmitter.emit(
XMPPEvents.CONNECTION_FAILED, // Strophe already has built-in HTTP/BOSH error handling and
// request retry logic. Requests are resent automatically
// until their error count reaches 5. Strophe.js disconnects
// if the error count is > 5. We are not replicating this
// here.
//
// The "problem" is that failed HTTP/BOSH requests don't
// trigger a callback with a status update, so when a
// callback with status Strophe.Status.DISCONNECTED arrives,
// we can't be sure if it's a graceful disconnect or if it's
// triggered by some HTTP/BOSH error.
//
// But that's a minor issue in Jitsi Meet as we never
// disconnect anyway, not even when the user closes the
// browser window (which is kind of wrong, but the point is
// that we should never ever get disconnected).
//
// On the other hand, failed connections due to XMPP layer
// errors, trigger a callback with status Strophe.Status.CONNFAIL.
//
// Here we implement retry logic for failed connections due
// to XMPP layer errors and we display an error to the user
// if we get disconnected from the XMPP server permanently.
// If the connection failed, retry.
if (connectionFailed
&& faultTolerantConnect.retry("connection-failed")) {
return;
}
// If we failed to connect to the XMPP server, fire an event
// to let all the interested module now about it.
eventEmitter.emit(XMPPEvents.CONNECTION_FAILED,
msg ? msg : lastErrorMsg); msg ? msg : lastErrorMsg);
} }
} else if (status === Strophe.Status.AUTHFAIL) { } else if (status === Strophe.Status.AUTHFAIL) {
@ -80,6 +148,7 @@ function connect(jid, password) {
} }
}); });
});
} }

View File

@ -20,7 +20,8 @@
"i18next-client": "1.7.7", "i18next-client": "1.7.7",
"sdp-interop": "jitsi/sdp-interop#f65fedfe57a", "sdp-interop": "jitsi/sdp-interop#f65fedfe57a",
"sdp-transform": "1.3.0", "sdp-transform": "1.3.0",
"async": "0.9.0" "async": "0.9.0",
"retry": "0.6.1"
}, },
"devDependencies": { "devDependencies": {
}, },