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.

JitsiConnection.ts 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import { getLogger } from '@jitsi/logger';
  2. import JitsiConference from './JitsiConference';
  3. import { JitsiConnectionEvents } from './JitsiConnectionEvents';
  4. import RTCStats from './modules/RTCStats/RTCStats';
  5. import FeatureFlags from './modules/flags/FeatureFlags';
  6. import Statistics from './modules/statistics/statistics';
  7. import XMPP from './modules/xmpp/xmpp';
  8. import {
  9. CONNECTION_DISCONNECTED as ANALYTICS_CONNECTION_DISCONNECTED,
  10. createConnectionFailedEvent
  11. } from './service/statistics/AnalyticsEvents';
  12. const logger = getLogger('JitsiConnection');
  13. export interface IConnectionOptions {
  14. analytics?: any;
  15. disableFocus?: boolean;
  16. enableWebsocketResume: boolean;
  17. flags?: Record<string, any>;
  18. name?: string;
  19. p2pStunServers: any[];
  20. serviceUrl: string;
  21. websocketKeepAlive?: number;
  22. websocketKeepAliveUrl?: number;
  23. xmppPing?: any;
  24. }
  25. export interface IConnectOptions {
  26. id?: string;
  27. name?: string;
  28. password?: string;
  29. }
  30. export interface IAttachOptions {
  31. jid: string;
  32. rid: string;
  33. sid: string;
  34. }
  35. /**
  36. * Creates a new connection object for the Jitsi Meet server side video
  37. * conferencing service. Provides access to the JitsiConference interface.
  38. */
  39. export default class JitsiConnection {
  40. private appID?: string;
  41. private token: string | null;
  42. private xmpp: XMPP;
  43. readonly options: IConnectionOptions;
  44. /**
  45. * Creates a new JitsiConnection instance.
  46. * @param appID - Identification for the provider of Jitsi Meet video conferencing services.
  47. * @param token - The JWT token used to authenticate with the server (optional).
  48. * @param options - Object with properties / settings related to connection with the server.
  49. */
  50. constructor(appID: string, token: string | null, options: IConnectionOptions) {
  51. this.appID = appID;
  52. this.token = token;
  53. this.options = options;
  54. // Initialize the feature flags so that they are advertised through the disco-info.
  55. FeatureFlags.init(options.flags || {});
  56. this.xmpp = new XMPP(options, token);
  57. this.addEventListener(JitsiConnectionEvents.CONNECTION_FAILED,
  58. (errType: string, msg: string, credentials: any, details: any) => {
  59. Statistics.sendAnalyticsAndLog(
  60. createConnectionFailedEvent(errType, msg, details));
  61. });
  62. this.addEventListener(JitsiConnectionEvents.CONNECTION_DISCONNECTED,
  63. (msg: string) => {
  64. // we can see disconnects from normal tab closing of the browser
  65. // and then there are no msgs, but we want to log only disconnects
  66. // when there is real error
  67. // XXX Do we need the difference in handling between the log and
  68. // analytics event here?
  69. if (msg) {
  70. Statistics.sendAnalytics(
  71. ANALYTICS_CONNECTION_DISCONNECTED,
  72. { message: msg });
  73. }
  74. });
  75. }
  76. /**
  77. * Connect the client with the server.
  78. * @param options - Connecting options (for example authentications parameters).
  79. * @param options.id - The username to use when connecting, if any.
  80. * @param options.password - The password to use when connecting with username, if any.
  81. * @param options.name - The name of the room/conference we will be connecting to. This is needed on connection
  82. * time to be able to send conference-request over http. If missing the flow where we send conference-iq to jicofo over
  83. * the established xmpp connection will be used, even in the case where we have configured conference http request url
  84. * to be used.
  85. */
  86. connect(options: IConnectOptions = {}): void {
  87. RTCStats.startWithConnection(this);
  88. // if we get redirected, we set disableFocus to skip sending the conference request twice
  89. if (this.xmpp.moderator.targetUrl && !this.options.disableFocus && options.name) {
  90. // The domain (optional) will uses this.options.hosts.muc.toLowerCase() if not provided
  91. this.xmpp.moderator.sendConferenceRequest(this.xmpp.getRoomJid(options.name, undefined))
  92. .then(() => {
  93. this.xmpp.connect(options.id, options.password);
  94. })
  95. .catch(e => logger.trace('sendConferenceRequest rejected', e));
  96. } else {
  97. this.xmpp.connect(options.id, options.password);
  98. }
  99. }
  100. /**
  101. * Attach to existing connection. Can be used for optimizations. For example:
  102. * if the connection is created on the server we can attach to it and start
  103. * using it.
  104. *
  105. * @param options - Connecting options - rid, sid and jid.
  106. */
  107. attach(options: IAttachOptions): void {
  108. this.xmpp.attach(options);
  109. }
  110. /**
  111. * Disconnect the client from the server.
  112. * @param args - Optional arguments to be passed to XMPP.disconnect
  113. * @returns Promise that resolves when the disconnect process is finished or rejects with an error.
  114. */
  115. disconnect(...args: [string?]): Promise<void> {
  116. // XXX Forward any arguments passed to JitsiConnection.disconnect to
  117. // XMPP.disconnect. For example, the caller of JitsiConnection.disconnect
  118. // may optionally pass the event which triggered the disconnect in order to
  119. // provide the implementation with finer-grained context.
  120. return this.xmpp.disconnect(...args);
  121. }
  122. /**
  123. * Returns the jid of the participant associated with the XMPP connection.
  124. *
  125. * @returns The jid of the participant.
  126. */
  127. getJid(): string {
  128. return this.xmpp.getJid();
  129. }
  130. /**
  131. * This method allows renewal of the tokens if they are expiring.
  132. * @param token - The new token.
  133. */
  134. setToken(token: string): void {
  135. this.token = token;
  136. }
  137. /**
  138. * Creates and joins new conference.
  139. * @param name - The name of the conference; if null - a generated name will be
  140. * provided from the api
  141. * @param options - Object with properties / settings related to the conference
  142. * that will be created.
  143. * @returns The new conference object.
  144. */
  145. initJitsiConference(name: string | null, options: Record<string, any>): JitsiConference {
  146. return new JitsiConference({
  147. name,
  148. config: options,
  149. connection: this
  150. });
  151. }
  152. /**
  153. * Subscribes the passed listener to the event.
  154. * @param event - The connection event.
  155. * @param listener - The function that will receive the event
  156. */
  157. addEventListener(event: JitsiConnectionEvents, listener: (...args: any[]) => void): void {
  158. this.xmpp.addListener(event, listener);
  159. }
  160. /**
  161. * Unsubscribes the passed handler.
  162. * @param event - The connection event.
  163. * @param listener - The function that will receive the event
  164. */
  165. removeEventListener(event: JitsiConnectionEvents, listener: (...args: any[]) => void): void {
  166. this.xmpp.removeListener(event, listener);
  167. }
  168. /**
  169. * Returns measured connectionTimes.
  170. * @returns Object containing connection timing information
  171. */
  172. getConnectionTimes(): Record<string, any> {
  173. return this.xmpp.connectionTimes;
  174. }
  175. /**
  176. * Adds new feature to the list of supported features for the local
  177. * participant.
  178. * @param feature - The name of the feature.
  179. * @param submit - If true - the new list of features will be
  180. * immediately submitted to the others.
  181. */
  182. addFeature(feature: string, submit: boolean = false): void {
  183. this.xmpp.caps.addFeature(feature, submit, true);
  184. }
  185. /**
  186. * Removes a feature from the list of supported features for the local
  187. * participant
  188. * @param feature - The name of the feature.
  189. * @param submit - If true - the new list of features will be
  190. * immediately submitted to the others.
  191. */
  192. removeFeature(feature: string, submit: boolean = false): void {
  193. this.xmpp.caps.removeFeature(feature, submit, true);
  194. }
  195. /**
  196. * Get object with internal logs.
  197. * @returns Object containing connection logs and metadata
  198. */
  199. getLogs(): Record<string, any> {
  200. const data = this.xmpp.getJingleLog();
  201. const metadata: Record<string, any> = {};
  202. metadata.time = new Date();
  203. metadata.url = window.location.href;
  204. metadata.ua = navigator.userAgent;
  205. const log = this.xmpp.getXmppLog();
  206. if (log) {
  207. metadata.xmpp = log;
  208. }
  209. data.metadata = metadata;
  210. return data;
  211. }
  212. }