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