jiti-meet/connection.js

263 lines
8.6 KiB
JavaScript
Raw Normal View History

2015-12-17 15:31:11 +00:00
/* global APP, JitsiMeetJS, config */
2016-11-11 15:00:54 +00:00
2020-07-09 07:17:23 +00:00
import { jitsiLocalStorage } from '@jitsi/js-utils';
2020-05-20 10:57:03 +00:00
import Logger from 'jitsi-meet-logger';
import { redirectToTokenAuthService } from './modules/UI/authentication/AuthHandler';
import { LoginDialog } from './react/features/authentication/components';
import { isTokenAuthEnabled } from './react/features/authentication/functions';
import {
connectionEstablished,
connectionFailed
} from './react/features/base/connection/actions';
import { openDialog } from './react/features/base/dialog/actions';
import { setJWT } from './react/features/base/jwt';
2017-02-19 00:42:11 +00:00
import {
isFatalJitsiConnectionError,
JitsiConnectionErrors,
JitsiConnectionEvents
2017-02-19 00:42:11 +00:00
} from './react/features/base/lib-jitsi-meet';
import { isVpaasMeeting } from './react/features/billing-counter/functions';
import { getJaasJWT } from './react/features/jaas/functions';
import { setPrejoinDisplayNameRequired } from './react/features/prejoin/actions';
2020-05-20 10:57:03 +00:00
const logger = Logger.getLogger(__filename);
2015-12-17 15:31:11 +00:00
/**
* The feature announced so we can distinguish jibri participants.
*
* @type {string}
*/
export const DISCO_JIBRI_FEATURE = 'http://jitsi.org/protocol/jibri';
/**
* Checks if we have data to use attach instead of connect. If we have the data
* executes attach otherwise check if we have to wait for the data. If we have
* to wait for the attach data we are setting handler to APP.connect.handler
* which is going to be called when the attach data is received otherwise
* executes connect.
*
* @param {string} [id] user id
* @param {string} [password] password
* @param {string} [roomName] the name of the conference.
*/
function checkForAttachParametersAndConnect(id, password, connection) {
if (window.XMPPAttachInfo) {
APP.connect.status = 'connecting';
2016-03-28 22:42:20 +00:00
// When connection optimization is not deployed or enabled the default
// value will be window.XMPPAttachInfo.status = "error"
// If the connection optimization is deployed and enabled and there is
2016-04-20 19:02:16 +00:00
// a failure the value will be window.XMPPAttachInfo.status = "error"
if (window.XMPPAttachInfo.status === 'error') {
connection.connect({
id,
password
});
return;
}
const attachOptions = window.XMPPAttachInfo.data;
if (attachOptions) {
connection.attach(attachOptions);
delete window.XMPPAttachInfo.data;
} else {
connection.connect({
id,
password
});
}
} else {
APP.connect.status = 'ready';
APP.connect.handler
= checkForAttachParametersAndConnect.bind(
null,
id, password, connection);
}
}
2016-01-15 14:59:35 +00:00
/**
* Try to open connection using provided credentials.
* @param {string} [id]
* @param {string} [password]
2016-02-09 23:44:41 +00:00
* @param {string} [roomName]
2016-01-15 14:59:35 +00:00
* @returns {Promise<JitsiConnection>} connection if
* everything is ok, else error.
*/
export async function connect(id, password, roomName) {
2017-04-21 10:00:50 +00:00
const connectionConfig = Object.assign({}, config);
const state = APP.store.getState();
let { jwt } = state['features/base/jwt'];
2021-07-16 12:14:37 +00:00
if (!jwt && isVpaasMeeting(state)) {
jwt = await getJaasJWT(state);
APP.store.dispatch(setJWT(jwt));
}
2016-02-09 23:44:41 +00:00
// Use Websocket URL for the web app if configured. Note that there is no 'isWeb' check, because there's assumption
// that this code executes only on web browsers/electron. This needs to be changed when mobile and web are unified.
let serviceUrl = connectionConfig.websocket || connectionConfig.bosh;
serviceUrl += `?room=${roomName}`;
// FIXME Remove deprecated 'bosh' option assignment at some point(LJM will be accepting only 'serviceUrl' option
// in future). It's included for the time being for Jitsi Meet and lib-jitsi-meet versions interoperability.
connectionConfig.serviceUrl = connectionConfig.bosh = serviceUrl;
2017-04-21 10:00:50 +00:00
if (connectionConfig.websocketKeepAliveUrl) {
connectionConfig.websocketKeepAliveUrl += `?room=${roomName}`;
}
const connection = new JitsiMeetJS.JitsiConnection(null, jwt, connectionConfig);
2015-12-17 15:31:11 +00:00
if (config.iAmRecorder) {
connection.addFeature(DISCO_JIBRI_FEATURE);
}
return new Promise((resolve, reject) => {
2015-12-17 15:31:11 +00:00
connection.addEventListener(
JitsiConnectionEvents.CONNECTION_ESTABLISHED,
2017-04-21 10:00:50 +00:00
handleConnectionEstablished);
2015-12-17 15:31:11 +00:00
connection.addEventListener(
JitsiConnectionEvents.CONNECTION_FAILED,
2017-04-21 10:00:50 +00:00
handleConnectionFailed);
connection.addEventListener(
JitsiConnectionEvents.CONNECTION_FAILED,
2017-04-21 10:00:50 +00:00
connectionFailedHandler);
connection.addEventListener(
JitsiConnectionEvents.DISPLAY_NAME_REQUIRED,
displayNameRequiredHandler
);
/* eslint-disable max-params */
/**
*
*/
function connectionFailedHandler(error, message, credentials, details) {
/* eslint-enable max-params */
APP.store.dispatch(
connectionFailed(
connection, {
credentials,
details,
message,
name: error
}));
2017-02-19 00:42:11 +00:00
if (isFatalJitsiConnectionError(error)) {
connection.removeEventListener(
JitsiConnectionEvents.CONNECTION_FAILED,
connectionFailedHandler);
}
}
2015-12-17 15:31:11 +00:00
/**
*
*/
2015-12-17 15:31:11 +00:00
function unsubscribe() {
connection.removeEventListener(
JitsiConnectionEvents.CONNECTION_ESTABLISHED,
2017-04-21 10:00:50 +00:00
handleConnectionEstablished);
2015-12-17 15:31:11 +00:00
connection.removeEventListener(
JitsiConnectionEvents.CONNECTION_FAILED,
2017-04-21 10:00:50 +00:00
handleConnectionFailed);
2015-12-17 15:31:11 +00:00
}
/**
*
*/
2015-12-17 15:31:11 +00:00
function handleConnectionEstablished() {
APP.store.dispatch(connectionEstablished(connection, Date.now()));
2015-12-17 15:31:11 +00:00
unsubscribe();
resolve(connection);
}
/**
*
*/
2015-12-17 15:31:11 +00:00
function handleConnectionFailed(err) {
unsubscribe();
logger.error('CONNECTION FAILED:', err);
2015-12-17 15:31:11 +00:00
reject(err);
}
/**
* Marks the display name for the prejoin screen as required.
* This can happen if a user tries to join a room with lobby enabled.
*/
function displayNameRequiredHandler() {
APP.store.dispatch(setPrejoinDisplayNameRequired());
}
checkForAttachParametersAndConnect(id, password, connection);
});
}
2015-12-17 15:31:11 +00:00
2016-01-15 14:59:35 +00:00
/**
* Open JitsiConnection using provided credentials.
* If retry option is true it will show auth dialog on PASSWORD_REQUIRED error.
*
* @param {object} options
* @param {string} [options.id]
* @param {string} [options.password]
2016-02-09 23:44:41 +00:00
* @param {string} [options.roomName]
2016-01-15 14:59:35 +00:00
* @param {boolean} [retry] if we should show auth dialog
* on PASSWORD_REQUIRED error.
*
* @returns {Promise<JitsiConnection>}
*/
export function openConnection({ id, password, retry, roomName }) {
const usernameOverride
= jitsiLocalStorage.getItem('xmpp_username_override');
const passwordOverride
= jitsiLocalStorage.getItem('xmpp_password_override');
2016-04-20 19:02:16 +00:00
2016-04-26 21:38:07 +00:00
if (usernameOverride && usernameOverride.length > 0) {
id = usernameOverride; // eslint-disable-line no-param-reassign
2016-04-20 19:02:16 +00:00
}
2016-04-26 21:38:07 +00:00
if (passwordOverride && passwordOverride.length > 0) {
password = passwordOverride; // eslint-disable-line no-param-reassign
2016-04-20 19:02:16 +00:00
}
2017-04-21 10:00:50 +00:00
return connect(id, password, roomName).catch(err => {
if (retry) {
const { jwt } = APP.store.getState()['features/base/jwt'];
2015-12-17 15:31:11 +00:00
if (err === JitsiConnectionErrors.PASSWORD_REQUIRED && !jwt) {
return requestAuth(roomName);
2015-12-17 15:31:11 +00:00
}
}
2017-04-21 10:00:50 +00:00
throw err;
2015-12-17 15:31:11 +00:00
});
}
/**
* Show Authentication Dialog and try to connect with new credentials.
* If failed to connect because of PASSWORD_REQUIRED error
* then ask for password again.
* @param {string} [roomName] name of the conference room
*
* @returns {Promise<JitsiConnection>}
*/
function requestAuth(roomName) {
const config = APP.store.getState()['features/base/config'];
if (isTokenAuthEnabled(config)) {
// This Promise never resolves as user gets redirected to another URL
return new Promise(() => redirectToTokenAuthService(roomName));
}
return new Promise(resolve => {
const onSuccess = connection => {
resolve(connection);
};
APP.store.dispatch(
openDialog(LoginDialog, { onSuccess,
roomName })
);
});
}