better error handling while establishing connection

This commit is contained in:
isymchych 2015-12-18 19:54:15 +02:00
parent 0ec8ab69a0
commit 3a00837107
7 changed files with 138 additions and 72 deletions

6
app.js
View File

@ -17,8 +17,6 @@ import URLProcessor from "./modules/config/URLProcessor";
import RoomnameGenerator from './modules/util/RoomnameGenerator';
import CQEvents from './service/connectionquality/CQEvents';
import UIEvents from './service/UI/UIEvents';
import LoginDialog from './modules/UI/authentication/LoginDialog';
import UIUtil from './modules/UI/util/UIUtil';
import {openConnection} from './modules/connection';
import AuthHandler from './modules/AuthHandler';
@ -149,6 +147,8 @@ function initConference(localTracks, connection) {
room.addTrack(track);
APP.UI.addLocalStream(track);
});
APP.UI.updateAuthInfo(room.isAuthEnabled(), room.getAuthLogin());
});
@ -534,6 +534,8 @@ function init() {
APP.statistics.start();
APP.connectionquality.init();
APP.keyboardshortcut.init();
}).catch(function (err) {
console.error(err);
});
}

View File

@ -34,7 +34,7 @@ function JitsiConference(options) {
this.connection = this.options.connection;
this.xmpp = this.connection.xmpp;
this.eventEmitter = new EventEmitter();
this.room = this.xmpp.createRoom(this.options.name, null, null, this.options.config);
this.room = this.xmpp.createRoom(this.options.name, this.options.config);
this.room.updateDeviceAvailability(RTC.getDeviceAvailability());
this.rtc = new RTC(this.room, options);
if(!RTC.options.disableAudioLevels)
@ -44,6 +44,8 @@ function JitsiConference(options) {
this.lastActiveSpeaker = null;
this.dtmfManager = null;
this.somebodySupportsDTMF = false;
this.authEnabled = false;
this.authIdentity;
}
/**
@ -78,6 +80,27 @@ JitsiConference.prototype.getName = function () {
return this.options.name;
};
/**
* Check if authentication is enabled for this conference.
*/
JitsiConference.prototype.isAuthEnabled = function () {
return this.authEnabled;
};
/**
* Check if user is logged in.
*/
JitsiConference.prototype.isLoggedIn = function () {
return !!this.authIdentity;
};
/**
* Get authorized login.
*/
JitsiConference.prototype.getAuthLogin = function () {
return this.authIdentity;
};
/**
* Check if external authentication is enabled for this conference.
*/
@ -385,6 +408,9 @@ JitsiConference.prototype.onMemberJoined = function (jid, email, nick) {
JitsiConference.prototype.onMemberLeft = function (jid) {
var id = Strophe.getResourceFromJid(jid);
if (id === 'focus') {
return;
}
var participant = this.participants[id];
delete this.participants[id];
this.eventEmitter.emit(JitsiConferenceEvents.USER_LEFT, id, participant);
@ -564,7 +590,8 @@ function setupListeners(conference) {
});
conference.room.addListener(AuthenticationEvents.IDENTITY_UPDATED, function (authEnabled, authIdentity) {
console.error(authEnabled, authIdentity);
conference.authEnabled = authEnabled;
conference.authIdentity = authIdentity;
});
conference.room.addListener(XMPPEvents.MESSAGE_RECEIVED, function (jid, displayName, txt, myJid, ts) {
@ -11522,12 +11549,12 @@ XMPP.prototype.connect = function (jid, password) {
return this._connect(jid, password);
};
XMPP.prototype.createRoom = function (roomName, options, useNicks, nick) {
XMPP.prototype.createRoom = function (roomName, options) {
var roomjid = roomName + '@' + this.options.hosts.muc;
if (useNicks) {
if (nick) {
roomjid += '/' + nick;
if (options.useNicks) {
if (options.nick) {
roomjid += '/' + options.nick;
} else {
roomjid += '/' + Strophe.getNodeFromJid(this.connection.jid);
}

View File

@ -612,10 +612,6 @@ UI.updateRemoteStats = function (jid, percent, stats) {
VideoLayout.updateConnectionStats(jid, percent, stats);
};
UI.showAuthenticateButton = function (show) {
Toolbar.showAuthenticateButton(show);
};
UI.markVideoInterrupted = function (interrupted) {
if (interrupted) {
VideoLayout.onVideoInterrupted();
@ -740,4 +736,15 @@ UI.notifyTokenAuthFailed = function () {
messageHandler.showError("dialog.error", "dialog.tokenAuthFailed");
};
UI.updateAuthInfo = function (isAuthEnabled, login) {
let loggedIn = !!login;
if (isAuthEnabled) {
Toolbar.setAuthenticatedIdentity(login);
Toolbar.showLoginButton(!loggedIn);
Toolbar.showLogoutButton(loggedIn);
}
};
module.exports = UI;

View File

@ -13,22 +13,53 @@ function getPasswordInputHtml() {
<h2 data-i18n="dialog.passwordRequired">${passRequiredMsg}</h2>
<input name="username" type="text" placeholder=${placeholder} autofocus>
<input name="password" type="password"
data-i18n="[placeholder]dialog.userPassword"
placeholder="user password">
`;
data-i18n="[placeholder]dialog.userPassword"
placeholder="user password">
`;
}
function toJid(id) {
if (id.indexOf("@") >= 0) {
return id;
}
let jid = id.concat('@');
if (config.hosts.authdomain) {
jid += config.hosts.authdomain;
} else {
jid += config.hosts.domain;
}
return jid;
}
function cancelButton() {
return {
title: APP.translation.generateTranslationHTML("dialog.Cancel"),
value: false
};
}
function Dialog(successCallback, cancelCallback) {
let loginButtons = [{
title: APP.translation.generateTranslationHTML("dialog.Ok"),
value: true
}];
let finishedButtons = [{
title: APP.translation.translateString('dialog.retry'),
value: 'retry'
}];
// show "cancel" button only if cancelCallback provided
if (cancelCallback) {
loginButtons.push(cancelButton());
finishedButtons.push(cancelButton());
}
const states = {
login: {
html: getPasswordInputHtml(),
buttons: [{
title: APP.translation.generateTranslationHTML("dialog.Ok"),
value: true
}, {
title: APP.translation.generateTranslationHTML("dialog.Cancel"),
value: false
}],
buttons: loginButtons,
focus: ':input:first',
submit: function (e, v, m, f) {
e.preventDefault();
@ -37,7 +68,7 @@ function Dialog(successCallback, cancelCallback) {
let password = f.password;
if (jid && password) {
connDialog.goToState('connecting');
successCallback(jid, password);
successCallback(toJid(jid), password);
}
} else {
// User cancelled
@ -54,13 +85,7 @@ function Dialog(successCallback, cancelCallback) {
finished: {
title: APP.translation.translateString('dialog.error'),
html: '<div id="errorMessage"></div>',
buttons: [{
title: APP.translation.translateString('dialog.retry'),
value: 'retry'
}, {
title: APP.translation.generateTranslationHTML("dialog.Cancel"),
value: false
}],
buttons: finishedButtons,
defaultButton: 0,
submit: function (e, v, m, f) {
e.preventDefault();

View File

@ -5,7 +5,7 @@ import LoginDialog from './UI/authentication/LoginDialog';
const ConnectionEvents = JitsiMeetJS.events.connection;
const ConnectionErrors = JitsiMeetJS.errors.connection;
export function openConnection({retry, id, password}) {
function connect(id, password) {
let connection = new JitsiMeetJS.JitsiConnection(null, null, {
hosts: config.hosts,
bosh: config.bosh,
@ -17,9 +17,8 @@ export function openConnection({retry, id, password}) {
ConnectionEvents.CONNECTION_ESTABLISHED, handleConnectionEstablished
);
connection.addEventListener(
ConnectionEvents.CONNECTION_FAILED, onConnectionFailed
ConnectionEvents.CONNECTION_FAILED, handleConnectionFailed
);
let authDialog;
function unsubscribe() {
connection.removeEventListener(
@ -27,11 +26,9 @@ export function openConnection({retry, id, password}) {
handleConnectionEstablished
);
connection.removeEventListener(
ConnectionEvents.CONNECTION_FAILED, onConnectionFailed
ConnectionEvents.CONNECTION_FAILED,
handleConnectionFailed
);
if (authDialog) {
authDialog.close();
}
}
function handleConnectionEstablished() {
@ -41,43 +38,49 @@ export function openConnection({retry, id, password}) {
function handleConnectionFailed(err) {
unsubscribe();
console.error("CONNECTION FAILED:", err);
reject(err);
}
function onConnectionFailed (err) {
console.error("CONNECTION FAILED:", err);
if (!retry) {
handleConnectionFailed(err);
return;
}
// retry only if auth failed
if (err !== ConnectionErrors.PASSWORD_REQUIRED) {
handleConnectionFailed(err);
return;
}
// do not retry if token is not valid
if (config.token) {
handleConnectionFailed(err);
return;
}
// ask for password and try again
if (authDialog) {
authDialog.displayError(err);
return;
}
authDialog = LoginDialog.showAuthDialog(
function (id, password) {
connection.connect({id, password});
}
);
}
connection.connect(id, password);
connection.connect({id, password});
});
}
function requestAuth() {
return new Promise(function (resolve, reject) {
let authDialog = LoginDialog.showAuthDialog(
function (id, password) {
connect(id, password).then(function (connection) {
authDialog.close();
resolve(connection);
}, function (err) {
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
authDialog.displayError(err);
} else {
authDialog.close();
reject(err);
}
});
}
);
});
}
export function openConnection({id, password, retry}) {
return connect(id, password).catch(function (err) {
if (!retry) {
throw err;
}
if (err === ConnectionErrors.PASSWORD_REQUIRED) {
// do not retry if token is not valid
if (config.token) {
throw err;
} else {
return requestAuth();
}
} else {
throw err;
}
});
}

View File

@ -73,6 +73,7 @@ module.exports = {
init: function () {
// Called when RTC finishes initialization
return;
APP.RTC.addListener(RTCEvents.RTC_READY,
function() {
screenObtainer.init(eventEmitter);

View File

@ -86,6 +86,7 @@ var statistics = {
stopRemote();
},
start: function () {
return;
APP.RTC.addStreamListener(onStreamCreated,
StreamEventTypes.EVENT_TYPE_LOCAL_CREATED);
APP.xmpp.addListener(XMPPEvents.DISPOSE_CONFERENCE,