You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

connection.js 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. /* global APP, JitsiMeetJS, config */
  2. import { jitsiLocalStorage } from '@jitsi/js-utils';
  3. import Logger from '@jitsi/logger';
  4. import { redirectToTokenAuthService } from './modules/UI/authentication/AuthHandler';
  5. import { LoginDialog } from './react/features/authentication/components';
  6. import { isTokenAuthEnabled } from './react/features/authentication/functions';
  7. import {
  8. connectionEstablished,
  9. connectionFailed,
  10. constructOptions
  11. } from './react/features/base/connection/actions.web';
  12. import { openDialog } from './react/features/base/dialog/actions';
  13. import { setJWT } from './react/features/base/jwt/actions';
  14. import {
  15. JitsiConnectionErrors,
  16. JitsiConnectionEvents
  17. } from './react/features/base/lib-jitsi-meet';
  18. import { isFatalJitsiConnectionError } from './react/features/base/lib-jitsi-meet/functions';
  19. import { getCustomerDetails } from './react/features/jaas/actions.any';
  20. import { getJaasJWT, isVpaasMeeting } from './react/features/jaas/functions';
  21. import {
  22. setPrejoinDisplayNameRequired
  23. } from './react/features/prejoin/actions';
  24. const logger = Logger.getLogger(__filename);
  25. /**
  26. * The feature announced so we can distinguish jibri participants.
  27. *
  28. * @type {string}
  29. */
  30. export const DISCO_JIBRI_FEATURE = 'http://jitsi.org/protocol/jibri';
  31. /**
  32. * Try to open connection using provided credentials.
  33. * @param {string} [id]
  34. * @param {string} [password]
  35. * @returns {Promise<JitsiConnection>} connection if
  36. * everything is ok, else error.
  37. */
  38. export async function connect(id, password) {
  39. const state = APP.store.getState();
  40. let { jwt } = state['features/base/jwt'];
  41. const { iAmRecorder, iAmSipGateway } = state['features/base/config'];
  42. if (!iAmRecorder && !iAmSipGateway && isVpaasMeeting(state)) {
  43. await APP.store.dispatch(getCustomerDetails());
  44. if (!jwt) {
  45. jwt = await getJaasJWT(state);
  46. APP.store.dispatch(setJWT(jwt));
  47. }
  48. }
  49. const connection = new JitsiMeetJS.JitsiConnection(null, jwt, constructOptions(state));
  50. if (config.iAmRecorder) {
  51. connection.addFeature(DISCO_JIBRI_FEATURE);
  52. }
  53. return new Promise((resolve, reject) => {
  54. connection.addEventListener(
  55. JitsiConnectionEvents.CONNECTION_ESTABLISHED,
  56. handleConnectionEstablished);
  57. connection.addEventListener(
  58. JitsiConnectionEvents.CONNECTION_FAILED,
  59. handleConnectionFailed);
  60. connection.addEventListener(
  61. JitsiConnectionEvents.CONNECTION_FAILED,
  62. connectionFailedHandler);
  63. connection.addEventListener(
  64. JitsiConnectionEvents.DISPLAY_NAME_REQUIRED,
  65. displayNameRequiredHandler
  66. );
  67. /* eslint-disable max-params */
  68. /**
  69. *
  70. */
  71. function connectionFailedHandler(error, message, credentials, details) {
  72. /* eslint-enable max-params */
  73. APP.store.dispatch(
  74. connectionFailed(
  75. connection, {
  76. credentials,
  77. details,
  78. message,
  79. name: error
  80. }));
  81. if (isFatalJitsiConnectionError(error)) {
  82. connection.removeEventListener(
  83. JitsiConnectionEvents.CONNECTION_FAILED,
  84. connectionFailedHandler);
  85. }
  86. }
  87. /**
  88. *
  89. */
  90. function unsubscribe() {
  91. connection.removeEventListener(
  92. JitsiConnectionEvents.CONNECTION_ESTABLISHED,
  93. handleConnectionEstablished);
  94. connection.removeEventListener(
  95. JitsiConnectionEvents.CONNECTION_FAILED,
  96. handleConnectionFailed);
  97. }
  98. /**
  99. *
  100. */
  101. function handleConnectionEstablished() {
  102. APP.store.dispatch(connectionEstablished(connection, Date.now()));
  103. unsubscribe();
  104. resolve(connection);
  105. }
  106. /**
  107. *
  108. */
  109. function handleConnectionFailed(err) {
  110. unsubscribe();
  111. logger.error('CONNECTION FAILED:', err);
  112. reject(err);
  113. }
  114. /**
  115. * Marks the display name for the prejoin screen as required.
  116. * This can happen if a user tries to join a room with lobby enabled.
  117. */
  118. function displayNameRequiredHandler() {
  119. APP.store.dispatch(setPrejoinDisplayNameRequired());
  120. }
  121. connection.connect({
  122. id,
  123. password
  124. });
  125. });
  126. }
  127. /**
  128. * Open JitsiConnection using provided credentials.
  129. * If retry option is true it will show auth dialog on PASSWORD_REQUIRED error.
  130. *
  131. * @param {object} options
  132. * @param {string} [options.id]
  133. * @param {string} [options.password]
  134. * @param {string} [options.roomName]
  135. * @param {boolean} [retry] if we should show auth dialog
  136. * on PASSWORD_REQUIRED error.
  137. *
  138. * @returns {Promise<JitsiConnection>}
  139. */
  140. export function openConnection({ id, password, retry, roomName }) {
  141. const usernameOverride
  142. = jitsiLocalStorage.getItem('xmpp_username_override');
  143. const passwordOverride
  144. = jitsiLocalStorage.getItem('xmpp_password_override');
  145. if (usernameOverride && usernameOverride.length > 0) {
  146. id = usernameOverride; // eslint-disable-line no-param-reassign
  147. }
  148. if (passwordOverride && passwordOverride.length > 0) {
  149. password = passwordOverride; // eslint-disable-line no-param-reassign
  150. }
  151. return connect(id, password).catch(err => {
  152. if (retry) {
  153. const { jwt } = APP.store.getState()['features/base/jwt'];
  154. if (err === JitsiConnectionErrors.PASSWORD_REQUIRED && !jwt) {
  155. return requestAuth(roomName);
  156. }
  157. }
  158. throw err;
  159. });
  160. }
  161. /**
  162. * Show Authentication Dialog and try to connect with new credentials.
  163. * If failed to connect because of PASSWORD_REQUIRED error
  164. * then ask for password again.
  165. * @param {string} [roomName] name of the conference room
  166. *
  167. * @returns {Promise<JitsiConnection>}
  168. */
  169. function requestAuth(roomName) {
  170. const config = APP.store.getState()['features/base/config'];
  171. if (isTokenAuthEnabled(config)) {
  172. // This Promise never resolves as user gets redirected to another URL
  173. return new Promise(() => redirectToTokenAuthService(roomName));
  174. }
  175. return new Promise(resolve => {
  176. const onSuccess = connection => {
  177. resolve(connection);
  178. };
  179. APP.store.dispatch(
  180. openDialog(LoginDialog, { onSuccess,
  181. roomName })
  182. );
  183. });
  184. }