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.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /* global APP, JitsiMeetJS, config */
  2. import AuthHandler from './modules/UI/authentication/AuthHandler';
  3. import jitsiLocalStorage from './modules/util/JitsiLocalStorage';
  4. import {
  5. connectionEstablished,
  6. connectionFailed
  7. } from './react/features/base/connection';
  8. import {
  9. isFatalJitsiConnectionError,
  10. JitsiConnectionErrors,
  11. JitsiConnectionEvents
  12. } from './react/features/base/lib-jitsi-meet';
  13. const logger = require('jitsi-meet-logger').getLogger(__filename);
  14. /**
  15. * The feature announced so we can distinguish jibri participants.
  16. *
  17. * @type {string}
  18. */
  19. export const DISCO_JIBRI_FEATURE = 'http://jitsi.org/protocol/jibri';
  20. /**
  21. * Checks if we have data to use attach instead of connect. If we have the data
  22. * executes attach otherwise check if we have to wait for the data. If we have
  23. * to wait for the attach data we are setting handler to APP.connect.handler
  24. * which is going to be called when the attach data is received otherwise
  25. * executes connect.
  26. *
  27. * @param {string} [id] user id
  28. * @param {string} [password] password
  29. * @param {string} [roomName] the name of the conference.
  30. */
  31. function checkForAttachParametersAndConnect(id, password, connection) {
  32. if (window.XMPPAttachInfo) {
  33. APP.connect.status = 'connecting';
  34. // When connection optimization is not deployed or enabled the default
  35. // value will be window.XMPPAttachInfo.status = "error"
  36. // If the connection optimization is deployed and enabled and there is
  37. // a failure the value will be window.XMPPAttachInfo.status = "error"
  38. if (window.XMPPAttachInfo.status === 'error') {
  39. connection.connect({
  40. id,
  41. password
  42. });
  43. return;
  44. }
  45. const attachOptions = window.XMPPAttachInfo.data;
  46. if (attachOptions) {
  47. connection.attach(attachOptions);
  48. delete window.XMPPAttachInfo.data;
  49. } else {
  50. connection.connect({
  51. id,
  52. password
  53. });
  54. }
  55. } else {
  56. APP.connect.status = 'ready';
  57. APP.connect.handler
  58. = checkForAttachParametersAndConnect.bind(
  59. null,
  60. id, password, connection);
  61. }
  62. }
  63. /**
  64. * Try to open connection using provided credentials.
  65. * @param {string} [id]
  66. * @param {string} [password]
  67. * @param {string} [roomName]
  68. * @returns {Promise<JitsiConnection>} connection if
  69. * everything is ok, else error.
  70. */
  71. function connect(id, password, roomName) {
  72. const connectionConfig = Object.assign({}, config);
  73. const { issuer, jwt } = APP.store.getState()['features/base/jwt'];
  74. // Use Websocket URL for the web app if configured. Note that there is no 'isWeb' check, because there's assumption
  75. // that this code executes only on web browsers/electron. This needs to be changed when mobile and web are unified.
  76. let serviceUrl = connectionConfig.websocket || connectionConfig.bosh;
  77. serviceUrl += `?room=${roomName}`;
  78. // FIXME Remove deprecated 'bosh' option assignment at some point(LJM will be accepting only 'serviceUrl' option
  79. // in future). It's included for the time being for Jitsi Meet and lib-jitsi-meet versions interoperability.
  80. connectionConfig.serviceUrl = connectionConfig.bosh = serviceUrl;
  81. const connection
  82. = new JitsiMeetJS.JitsiConnection(
  83. null,
  84. jwt && issuer && issuer !== 'anonymous' ? jwt : undefined,
  85. connectionConfig);
  86. if (config.iAmRecorder) {
  87. connection.addFeature(DISCO_JIBRI_FEATURE);
  88. }
  89. return new Promise((resolve, reject) => {
  90. connection.addEventListener(
  91. JitsiConnectionEvents.CONNECTION_ESTABLISHED,
  92. handleConnectionEstablished);
  93. connection.addEventListener(
  94. JitsiConnectionEvents.CONNECTION_FAILED,
  95. handleConnectionFailed);
  96. connection.addEventListener(
  97. JitsiConnectionEvents.CONNECTION_FAILED,
  98. connectionFailedHandler);
  99. /* eslint-disable max-params */
  100. /**
  101. *
  102. */
  103. function connectionFailedHandler(error, message, credentials, details) {
  104. /* eslint-enable max-params */
  105. APP.store.dispatch(
  106. connectionFailed(
  107. connection, {
  108. credentials,
  109. details,
  110. message,
  111. name: error
  112. }));
  113. if (isFatalJitsiConnectionError(error)) {
  114. connection.removeEventListener(
  115. JitsiConnectionEvents.CONNECTION_FAILED,
  116. connectionFailedHandler);
  117. }
  118. }
  119. /**
  120. *
  121. */
  122. function unsubscribe() {
  123. connection.removeEventListener(
  124. JitsiConnectionEvents.CONNECTION_ESTABLISHED,
  125. handleConnectionEstablished);
  126. connection.removeEventListener(
  127. JitsiConnectionEvents.CONNECTION_FAILED,
  128. handleConnectionFailed);
  129. }
  130. /**
  131. *
  132. */
  133. function handleConnectionEstablished() {
  134. APP.store.dispatch(connectionEstablished(connection, Date.now()));
  135. unsubscribe();
  136. resolve(connection);
  137. }
  138. /**
  139. *
  140. */
  141. function handleConnectionFailed(err) {
  142. unsubscribe();
  143. logger.error('CONNECTION FAILED:', err);
  144. reject(err);
  145. }
  146. checkForAttachParametersAndConnect(id, password, connection);
  147. });
  148. }
  149. /**
  150. * Open JitsiConnection using provided credentials.
  151. * If retry option is true it will show auth dialog on PASSWORD_REQUIRED error.
  152. *
  153. * @param {object} options
  154. * @param {string} [options.id]
  155. * @param {string} [options.password]
  156. * @param {string} [options.roomName]
  157. * @param {boolean} [retry] if we should show auth dialog
  158. * on PASSWORD_REQUIRED error.
  159. *
  160. * @returns {Promise<JitsiConnection>}
  161. */
  162. export function openConnection({ id, password, retry, roomName }) {
  163. const usernameOverride
  164. = jitsiLocalStorage.getItem('xmpp_username_override');
  165. const passwordOverride
  166. = jitsiLocalStorage.getItem('xmpp_password_override');
  167. if (usernameOverride && usernameOverride.length > 0) {
  168. id = usernameOverride; // eslint-disable-line no-param-reassign
  169. }
  170. if (passwordOverride && passwordOverride.length > 0) {
  171. password = passwordOverride; // eslint-disable-line no-param-reassign
  172. }
  173. return connect(id, password, roomName).catch(err => {
  174. if (retry) {
  175. const { issuer, jwt } = APP.store.getState()['features/base/jwt'];
  176. if (err === JitsiConnectionErrors.PASSWORD_REQUIRED
  177. && (!jwt || issuer === 'anonymous')) {
  178. return AuthHandler.requestAuth(roomName, connect);
  179. }
  180. }
  181. throw err;
  182. });
  183. }