|
@@ -1,21 +1,25 @@
|
1
|
1
|
/* global $, APP, config, Strophe */
|
2
|
|
-
|
3
|
|
-var logger = require("jitsi-meet-logger").getLogger(__filename);
|
4
|
|
-var EventEmitter = require("events");
|
5
|
|
-var Pako = require("pako");
|
6
|
|
-var RandomUtil = require("../util/RandomUtil");
|
7
|
|
-var RTCEvents = require("../../service/RTC/RTCEvents");
|
8
|
|
-var XMPPEvents = require("../../service/xmpp/XMPPEvents");
|
|
2
|
+import {getLogger} from "jitsi-meet-logger";
|
|
3
|
+const logger = getLogger(__filename);
|
|
4
|
+import EventEmitter from "events";
|
|
5
|
+import Pako from "pako";
|
|
6
|
+import RandomUtil from "../util/RandomUtil";
|
|
7
|
+import RTCEvents from "../../service/RTC/RTCEvents";
|
|
8
|
+import XMPPEvents from "../../service/xmpp/XMPPEvents";
|
9
|
9
|
import * as JitsiConnectionErrors from "../../JitsiConnectionErrors";
|
10
|
10
|
import * as JitsiConnectionEvents from "../../JitsiConnectionEvents";
|
11
|
|
-var RTC = require("../RTC/RTC");
|
12
|
|
-var RTCBrowserType = require("../RTC/RTCBrowserType");
|
13
|
|
-
|
14
|
|
-var authenticatedUser = false;
|
15
|
|
-
|
16
|
|
-function createConnection(bosh, token) {
|
17
|
|
- bosh = bosh || '/http-bind';
|
18
|
|
-
|
|
11
|
+import RTC from "../RTC/RTC";
|
|
12
|
+import RTCBrowserType from "../RTC/RTCBrowserType";
|
|
13
|
+import initEmuc from "./strophe.emuc";
|
|
14
|
+import initJingle from "./strophe.jingle";
|
|
15
|
+import initStropheUtil from "./strophe.util";
|
|
16
|
+import initPing from "./strophe.ping";
|
|
17
|
+import initRayo from "./strophe.rayo";
|
|
18
|
+import initStropheLogger from "./strophe.logger";
|
|
19
|
+
|
|
20
|
+let authenticatedUser = true;
|
|
21
|
+
|
|
22
|
+function createConnection(token, bosh = '/http-bind') {
|
19
|
23
|
// Append token as URL param
|
20
|
24
|
if (token) {
|
21
|
25
|
bosh += (bosh.indexOf('?') == -1 ? '?' : '&') + 'token=' + token;
|
|
@@ -24,79 +28,43 @@ function createConnection(bosh, token) {
|
24
|
28
|
return new Strophe.Connection(bosh);
|
25
|
29
|
};
|
26
|
30
|
|
27
|
|
-//!!!!!!!!!! FIXME: ...
|
28
|
|
-function initStrophePlugins(XMPP) {
|
29
|
|
- require("./strophe.emuc")(XMPP);
|
30
|
|
- require("./strophe.jingle")(XMPP, XMPP.eventEmitter);
|
31
|
|
-// require("./strophe.moderate")(XMPP, eventEmitter);
|
32
|
|
- require("./strophe.util")();
|
33
|
|
- require("./strophe.ping")(XMPP, XMPP.eventEmitter);
|
34
|
|
- require("./strophe.rayo")();
|
35
|
|
- require("./strophe.logger")();
|
36
|
|
-}
|
37
|
|
-
|
38
|
|
-function XMPP(options, token) {
|
39
|
|
- this.eventEmitter = new EventEmitter();
|
40
|
|
- this.connection = null;
|
41
|
|
- this.disconnectInProgress = false;
|
42
|
|
- this.connectionTimes = {};
|
43
|
|
- this.forceMuted = false;
|
44
|
|
- this.options = options;
|
45
|
|
- this.connectParams = {};
|
46
|
|
- this.token = token;
|
47
|
|
- initStrophePlugins(this);
|
48
|
|
-
|
49
|
|
- this.connection = createConnection(options.bosh, token);
|
50
|
|
-
|
51
|
|
- if(!this.connection.disco || !this.connection.caps)
|
52
|
|
- throw new Error(
|
53
|
|
- "Missing strophe-plugins (disco and caps plugins are required)!");
|
54
|
|
-
|
55
|
|
- // Initialize features advertised in disco-info
|
56
|
|
- this.initFeaturesList();
|
57
|
|
-
|
58
|
|
- // Setup a disconnect on unload as a way to facilitate API consumers. It
|
59
|
|
- // sounds like they would want that. A problem for them though may be if
|
60
|
|
- // they wanted to utilize the connected connection in an unload handler of
|
61
|
|
- // their own. However, it should be fairly easy for them to do that by
|
62
|
|
- // registering their unload handler before us.
|
63
|
|
- $(window).on('beforeunload unload', this.disconnect.bind(this));
|
64
|
|
-}
|
65
|
|
-
|
66
|
|
-/**
|
67
|
|
- * Reloads the XMPP module
|
68
|
|
- */
|
69
|
|
-XMPP.prototype.reload = function () {
|
70
|
|
- this.disconnect();
|
71
|
|
- this.connection.pause();
|
72
|
|
- this.connection = createConnection(this.options.bosh, this.token);
|
73
|
|
-
|
74
|
|
- // Initialize features advertised in disco-info
|
75
|
|
- this.initFeaturesList();
|
76
|
|
-
|
77
|
|
- //getData for attach
|
78
|
|
- if(this.options.prebindURL &&
|
79
|
|
- typeof(createConnectionExternally) === "function") {
|
80
|
|
- var self = this;
|
81
|
|
- createConnectionExternally(this.options.prebindURL, function (data) {
|
82
|
|
- self.attach(data);
|
83
|
|
- }, function (error) {
|
84
|
|
- //connect
|
85
|
|
- self.connect(this.connectParams.jid, this.connectParams.password);
|
86
|
|
- });
|
87
|
|
- } else {
|
88
|
|
- //connect
|
89
|
|
- this.connect(this.connectParams.jid, this.connectParams.password);
|
|
31
|
+export default class XMPP {
|
|
32
|
+ constructor(options, token) {
|
|
33
|
+ this.eventEmitter = new EventEmitter();
|
|
34
|
+ this.connection = null;
|
|
35
|
+ this.disconnectInProgress = false;
|
|
36
|
+ this.connectionTimes = {};
|
|
37
|
+ this.forceMuted = false;
|
|
38
|
+ this.options = options;
|
|
39
|
+ this.connectParams = {};
|
|
40
|
+ this.token = token;
|
|
41
|
+ this._initStrophePlugins(this);
|
|
42
|
+
|
|
43
|
+ this.connection = createConnection(options.bosh, token);
|
|
44
|
+
|
|
45
|
+ if(!this.connection.disco || !this.connection.caps)
|
|
46
|
+ throw new Error(
|
|
47
|
+ "Missing strophe-plugins (disco and caps plugins are required)!");
|
|
48
|
+
|
|
49
|
+ // Initialize features advertised in disco-info
|
|
50
|
+ this.initFeaturesList();
|
|
51
|
+
|
|
52
|
+ // Setup a disconnect on unload as a way to facilitate API consumers. It
|
|
53
|
+ // sounds like they would want that. A problem for them though may be if
|
|
54
|
+ // they wanted to utilize the connected connection in an unload handler of
|
|
55
|
+ // their own. However, it should be fairly easy for them to do that by
|
|
56
|
+ // registering their unload handler before us.
|
|
57
|
+ $(window).on('beforeunload unload', this.disconnect.bind(this));
|
90
|
58
|
}
|
91
|
59
|
|
92
|
|
-}
|
|
60
|
+ /**
|
|
61
|
+ * Initializes the list of feature advertised through the disco-info mechanism
|
|
62
|
+ */
|
|
63
|
+ initFeaturesList () {
|
|
64
|
+ const disco = this.connection.disco;
|
|
65
|
+ if (!disco)
|
|
66
|
+ return;
|
93
|
67
|
|
94
|
|
-/**
|
95
|
|
- * Initializes the list of feature advertised through the disco-info mechanism
|
96
|
|
- */
|
97
|
|
-XMPP.prototype.initFeaturesList = function () {
|
98
|
|
- var disco = this.connection.disco;
|
99
|
|
- if (disco) {
|
100
|
68
|
// http://xmpp.org/extensions/xep-0167.html#support
|
101
|
69
|
// http://xmpp.org/extensions/xep-0176.html#support
|
102
|
70
|
disco.addFeature('urn:xmpp:jingle:1');
|
|
@@ -124,288 +92,292 @@ XMPP.prototype.initFeaturesList = function () {
|
124
|
92
|
// Enable Lipsync ?
|
125
|
93
|
if (RTCBrowserType.isChrome() && false !== this.options.enableLipSync) {
|
126
|
94
|
logger.info("Lip-sync enabled !");
|
127
|
|
- this.connection.disco.addFeature('http://jitsi.org/meet/lipsync');
|
|
95
|
+ disco.addFeature('http://jitsi.org/meet/lipsync');
|
128
|
96
|
}
|
129
|
97
|
}
|
130
|
|
-};
|
131
|
98
|
|
132
|
|
-XMPP.prototype.getConnection = function () { return this.connection; };
|
133
|
|
-
|
134
|
|
-/**
|
135
|
|
- * Receive connection status changes and handles them.
|
136
|
|
- * @password {string} the password passed in connect method
|
137
|
|
- * @status the connection status
|
138
|
|
- * @msg message
|
139
|
|
- */
|
140
|
|
-XMPP.prototype.connectionHandler = function (password, status, msg) {
|
141
|
|
- var now = window.performance.now();
|
142
|
|
- this.connectionTimes[Strophe.getStatusString(status).toLowerCase()] = now;
|
143
|
|
- logger.log("(TIME) Strophe " + Strophe.getStatusString(status) +
|
144
|
|
- (msg ? "[" + msg + "]" : "") + ":\t", now);
|
145
|
|
- if (status === Strophe.Status.CONNECTED ||
|
146
|
|
- status === Strophe.Status.ATTACHED) {
|
147
|
|
- if (this.options.useStunTurn) {
|
148
|
|
- this.connection.jingle.getStunAndTurnCredentials();
|
149
|
|
- }
|
150
|
|
-
|
151
|
|
- logger.info("My Jabber ID: " + this.connection.jid);
|
152
|
|
-
|
153
|
|
- // Schedule ping ?
|
154
|
|
- var pingJid = this.connection.domain;
|
155
|
|
- this.connection.ping.hasPingSupport(
|
156
|
|
- pingJid,
|
157
|
|
- function (hasPing) {
|
158
|
|
- if (hasPing)
|
159
|
|
- this.connection.ping.startInterval(pingJid);
|
160
|
|
- else
|
161
|
|
- logger.warn("Ping NOT supported by " + pingJid);
|
162
|
|
- }.bind(this));
|
163
|
|
-
|
164
|
|
- if (password)
|
165
|
|
- authenticatedUser = true;
|
166
|
|
- if (this.connection && this.connection.connected &&
|
167
|
|
- Strophe.getResourceFromJid(this.connection.jid)) {
|
168
|
|
- // .connected is true while connecting?
|
169
|
|
-// this.connection.send($pres());
|
170
|
|
- this.eventEmitter.emit(
|
171
|
|
- JitsiConnectionEvents.CONNECTION_ESTABLISHED,
|
172
|
|
- Strophe.getResourceFromJid(this.connection.jid));
|
173
|
|
- }
|
174
|
|
- } else if (status === Strophe.Status.CONNFAIL) {
|
175
|
|
- if (msg === 'x-strophe-bad-non-anon-jid') {
|
176
|
|
- this.anonymousConnectionFailed = true;
|
177
|
|
- } else {
|
178
|
|
- this.connectionFailed = true;
|
179
|
|
- }
|
180
|
|
- this.lastErrorMsg = msg;
|
181
|
|
- } else if (status === Strophe.Status.DISCONNECTED) {
|
182
|
|
- // Stop ping interval
|
183
|
|
- this.connection.ping.stopInterval();
|
184
|
|
- this.disconnectInProgress = false;
|
185
|
|
- if (this.anonymousConnectionFailed) {
|
186
|
|
- // prompt user for username and password
|
|
99
|
+ getConnection () { return this.connection; }
|
|
100
|
+
|
|
101
|
+ /**
|
|
102
|
+ * Receive connection status changes and handles them.
|
|
103
|
+ * @password {string} the password passed in connect method
|
|
104
|
+ * @status the connection status
|
|
105
|
+ * @msg message
|
|
106
|
+ */
|
|
107
|
+ connectionHandler (password, status, msg) {
|
|
108
|
+ const now = window.performance.now();
|
|
109
|
+ const statusStr = Strophe.getStatusString(status).toLowerCase();
|
|
110
|
+ this.connectionTimes[statusStr] = now;
|
|
111
|
+ logger.log("(TIME) Strophe " + statusStr +
|
|
112
|
+ (msg ? "[" + msg + "]" : "") + ":\t", now);
|
|
113
|
+ if (status === Strophe.Status.CONNECTED ||
|
|
114
|
+ status === Strophe.Status.ATTACHED) {
|
|
115
|
+ if (this.options.useStunTurn) {
|
|
116
|
+ this.connection.jingle.getStunAndTurnCredentials();
|
|
117
|
+ }
|
|
118
|
+
|
|
119
|
+ logger.info("My Jabber ID: " + this.connection.jid);
|
|
120
|
+
|
|
121
|
+ // Schedule ping ?
|
|
122
|
+ var pingJid = this.connection.domain;
|
|
123
|
+ this.connection.ping.hasPingSupport(
|
|
124
|
+ pingJid,
|
|
125
|
+ function (hasPing) {
|
|
126
|
+ if (hasPing)
|
|
127
|
+ this.connection.ping.startInterval(pingJid);
|
|
128
|
+ else
|
|
129
|
+ logger.warn("Ping NOT supported by " + pingJid);
|
|
130
|
+ }.bind(this));
|
|
131
|
+
|
|
132
|
+ if (password)
|
|
133
|
+ authenticatedUser = true;
|
|
134
|
+ if (this.connection && this.connection.connected &&
|
|
135
|
+ Strophe.getResourceFromJid(this.connection.jid)) {
|
|
136
|
+ // .connected is true while connecting?
|
|
137
|
+ // this.connection.send($pres());
|
|
138
|
+ this.eventEmitter.emit(
|
|
139
|
+ JitsiConnectionEvents.CONNECTION_ESTABLISHED,
|
|
140
|
+ Strophe.getResourceFromJid(this.connection.jid));
|
|
141
|
+ }
|
|
142
|
+ } else if (status === Strophe.Status.CONNFAIL) {
|
|
143
|
+ if (msg === 'x-strophe-bad-non-anon-jid') {
|
|
144
|
+ this.anonymousConnectionFailed = true;
|
|
145
|
+ } else {
|
|
146
|
+ this.connectionFailed = true;
|
|
147
|
+ }
|
|
148
|
+ this.lastErrorMsg = msg;
|
|
149
|
+ } else if (status === Strophe.Status.DISCONNECTED) {
|
|
150
|
+ // Stop ping interval
|
|
151
|
+ this.connection.ping.stopInterval();
|
|
152
|
+ this.disconnectInProgress = false;
|
|
153
|
+ if (this.anonymousConnectionFailed) {
|
|
154
|
+ // prompt user for username and password
|
|
155
|
+ this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED,
|
|
156
|
+ JitsiConnectionErrors.PASSWORD_REQUIRED);
|
|
157
|
+ } else if(this.connectionFailed) {
|
|
158
|
+ this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED,
|
|
159
|
+ JitsiConnectionErrors.OTHER_ERROR,
|
|
160
|
+ msg ? msg : this.lastErrorMsg);
|
|
161
|
+ } else {
|
|
162
|
+ this.eventEmitter.emit(
|
|
163
|
+ JitsiConnectionEvents.CONNECTION_DISCONNECTED,
|
|
164
|
+ msg ? msg : this.lastErrorMsg);
|
|
165
|
+ }
|
|
166
|
+ } else if (status === Strophe.Status.AUTHFAIL) {
|
|
167
|
+ // wrong password or username, prompt user
|
187
|
168
|
this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED,
|
188
|
169
|
JitsiConnectionErrors.PASSWORD_REQUIRED);
|
189
|
|
- } else if(this.connectionFailed) {
|
190
|
|
- this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED,
|
191
|
|
- JitsiConnectionErrors.OTHER_ERROR,
|
192
|
|
- msg ? msg : this.lastErrorMsg);
|
193
|
|
- } else {
|
194
|
|
- this.eventEmitter.emit(
|
195
|
|
- JitsiConnectionEvents.CONNECTION_DISCONNECTED,
|
196
|
|
- msg ? msg : this.lastErrorMsg);
|
197
|
|
- }
|
198
|
|
- } else if (status === Strophe.Status.AUTHFAIL) {
|
199
|
|
- // wrong password or username, prompt user
|
200
|
|
- this.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_FAILED,
|
201
|
|
- JitsiConnectionErrors.PASSWORD_REQUIRED);
|
202
|
170
|
|
|
171
|
+ }
|
203
|
172
|
}
|
204
|
|
-}
|
205
|
173
|
|
206
|
|
-XMPP.prototype._connect = function (jid, password) {
|
207
|
|
- // connection.connect() starts the connection process.
|
208
|
|
- //
|
209
|
|
- // As the connection process proceeds, the user supplied callback will
|
210
|
|
- // be triggered multiple times with status updates. The callback should
|
211
|
|
- // take two arguments - the status code and the error condition.
|
212
|
|
- //
|
213
|
|
- // The status code will be one of the values in the Strophe.Status
|
214
|
|
- // constants. The error condition will be one of the conditions defined
|
215
|
|
- // in RFC 3920 or the condition ‘strophe-parsererror’.
|
216
|
|
- //
|
217
|
|
- // The Parameters wait, hold and route are optional and only relevant
|
218
|
|
- // for BOSH connections. Please see XEP 124 for a more detailed
|
219
|
|
- // explanation of the optional parameters.
|
220
|
|
- //
|
221
|
|
- // Connection status constants for use by the connection handler
|
222
|
|
- // callback.
|
223
|
|
- //
|
224
|
|
- // Status.ERROR - An error has occurred (websockets specific)
|
225
|
|
- // Status.CONNECTING - The connection is currently being made
|
226
|
|
- // Status.CONNFAIL - The connection attempt failed
|
227
|
|
- // Status.AUTHENTICATING - The connection is authenticating
|
228
|
|
- // Status.AUTHFAIL - The authentication attempt failed
|
229
|
|
- // Status.CONNECTED - The connection has succeeded
|
230
|
|
- // Status.DISCONNECTED - The connection has been terminated
|
231
|
|
- // Status.DISCONNECTING - The connection is currently being terminated
|
232
|
|
- // Status.ATTACHED - The connection has been attached
|
233
|
|
-
|
234
|
|
- this.anonymousConnectionFailed = false;
|
235
|
|
- this.connectionFailed = false;
|
236
|
|
- this.lastErrorMsg = undefined;
|
237
|
|
- this.connection.connect(jid, password,
|
238
|
|
- this.connectionHandler.bind(this, password));
|
239
|
|
-}
|
|
174
|
+ _connect (jid, password) {
|
|
175
|
+ // connection.connect() starts the connection process.
|
|
176
|
+ //
|
|
177
|
+ // As the connection process proceeds, the user supplied callback will
|
|
178
|
+ // be triggered multiple times with status updates. The callback should
|
|
179
|
+ // take two arguments - the status code and the error condition.
|
|
180
|
+ //
|
|
181
|
+ // The status code will be one of the values in the Strophe.Status
|
|
182
|
+ // constants. The error condition will be one of the conditions defined
|
|
183
|
+ // in RFC 3920 or the condition ‘strophe-parsererror’.
|
|
184
|
+ //
|
|
185
|
+ // The Parameters wait, hold and route are optional and only relevant
|
|
186
|
+ // for BOSH connections. Please see XEP 124 for a more detailed
|
|
187
|
+ // explanation of the optional parameters.
|
|
188
|
+ //
|
|
189
|
+ // Connection status constants for use by the connection handler
|
|
190
|
+ // callback.
|
|
191
|
+ //
|
|
192
|
+ // Status.ERROR - An error has occurred (websockets specific)
|
|
193
|
+ // Status.CONNECTING - The connection is currently being made
|
|
194
|
+ // Status.CONNFAIL - The connection attempt failed
|
|
195
|
+ // Status.AUTHENTICATING - The connection is authenticating
|
|
196
|
+ // Status.AUTHFAIL - The authentication attempt failed
|
|
197
|
+ // Status.CONNECTED - The connection has succeeded
|
|
198
|
+ // Status.DISCONNECTED - The connection has been terminated
|
|
199
|
+ // Status.DISCONNECTING - The connection is currently being terminated
|
|
200
|
+ // Status.ATTACHED - The connection has been attached
|
|
201
|
+
|
|
202
|
+ this.anonymousConnectionFailed = false;
|
|
203
|
+ this.connectionFailed = false;
|
|
204
|
+ this.lastErrorMsg = undefined;
|
|
205
|
+ this.connection.connect(jid, password,
|
|
206
|
+ this.connectionHandler.bind(this, password));
|
|
207
|
+ }
|
240
|
208
|
|
241
|
|
-/**
|
242
|
|
- * Attach to existing connection. Can be used for optimizations. For example:
|
243
|
|
- * if the connection is created on the server we can attach to it and start
|
244
|
|
- * using it.
|
245
|
|
- *
|
246
|
|
- * @param options {object} connecting options - rid, sid, jid and password.
|
247
|
|
- */
|
248
|
|
- XMPP.prototype.attach = function (options) {
|
249
|
|
- var now = this.connectionTimes["attaching"] = window.performance.now();
|
250
|
|
- logger.log("(TIME) Strophe Attaching\t:" + now);
|
251
|
|
- this.connection.attach(options.jid, options.sid, parseInt(options.rid,10)+1,
|
252
|
|
- this.connectionHandler.bind(this, options.password));
|
253
|
|
-}
|
|
209
|
+ /**
|
|
210
|
+ * Attach to existing connection. Can be used for optimizations. For example:
|
|
211
|
+ * if the connection is created on the server we can attach to it and start
|
|
212
|
+ * using it.
|
|
213
|
+ *
|
|
214
|
+ * @param options {object} connecting options - rid, sid, jid and password.
|
|
215
|
+ */
|
|
216
|
+ attach (options) {
|
|
217
|
+ const now = this.connectionTimes["attaching"] = window.performance.now();
|
|
218
|
+ logger.log("(TIME) Strophe Attaching\t:" + now);
|
|
219
|
+ this.connection.attach(options.jid, options.sid,
|
|
220
|
+ parseInt(options.rid,10)+1,
|
|
221
|
+ this.connectionHandler.bind(this, options.password));
|
|
222
|
+ }
|
254
|
223
|
|
255
|
|
-XMPP.prototype.connect = function (jid, password) {
|
256
|
|
- this.connectParams = {
|
257
|
|
- jid: jid,
|
258
|
|
- password: password
|
259
|
|
- };
|
260
|
|
- if (!jid) {
|
261
|
|
- var configDomain
|
262
|
|
- = this.options.hosts.anonymousdomain || this.options.hosts.domain;
|
263
|
|
- // Force authenticated domain if room is appended with '?login=true'
|
264
|
|
- // or if we're joining with the token
|
265
|
|
- if (this.options.hosts.anonymousdomain
|
266
|
|
- && (window.location.search.indexOf("login=true") !== -1
|
267
|
|
- || this.options.token)) {
|
268
|
|
- configDomain = this.options.hosts.domain;
|
|
224
|
+ connect (jid, password) {
|
|
225
|
+ this.connectParams = {
|
|
226
|
+ jid: jid,
|
|
227
|
+ password: password
|
|
228
|
+ };
|
|
229
|
+ if (!jid) {
|
|
230
|
+ let configDomain
|
|
231
|
+ = this.options.hosts.anonymousdomain ||
|
|
232
|
+ this.options.hosts.domain;
|
|
233
|
+ // Force authenticated domain if room is appended with '?login=true'
|
|
234
|
+ // or if we're joining with the token
|
|
235
|
+ if (this.options.hosts.anonymousdomain
|
|
236
|
+ && (window.location.search.indexOf("login=true") !== -1
|
|
237
|
+ || this.options.token)) {
|
|
238
|
+ configDomain = this.options.hosts.domain;
|
|
239
|
+ }
|
|
240
|
+ jid = configDomain || window.location.hostname;
|
269
|
241
|
}
|
270
|
|
- jid = configDomain || window.location.hostname;
|
|
242
|
+ return this._connect(jid, password);
|
271
|
243
|
}
|
272
|
|
- return this._connect(jid, password);
|
273
|
|
-};
|
274
|
|
-
|
275
|
|
-XMPP.prototype.createRoom = function (roomName, options, settings) {
|
276
|
|
- var roomjid = roomName + '@' + this.options.hosts.muc;
|
277
|
244
|
|
278
|
|
- if (options.useNicks) {
|
279
|
|
- if (options.nick) {
|
280
|
|
- roomjid += '/' + options.nick;
|
281
|
|
- } else {
|
282
|
|
- roomjid += '/' + Strophe.getNodeFromJid(this.connection.jid);
|
283
|
|
- }
|
284
|
|
- } else {
|
285
|
|
- var tmpJid = Strophe.getNodeFromJid(this.connection.jid);
|
|
245
|
+ createRoom (roomName, options, settings) {
|
|
246
|
+ let tmpJid = Strophe.getNodeFromJid(this.connection.jid);
|
|
247
|
+ let roomjid = roomName + "@" + this.options.hosts.muc + "/";
|
286
|
248
|
|
287
|
|
- if (!authenticatedUser)
|
288
|
|
- tmpJid = tmpJid.substr(0, 8);
|
289
|
|
- else
|
290
|
|
- tmpJid += "-" + RandomUtil.randomHexString(6);
|
|
249
|
+ roomjid += (options.useNicks)? options.nick || tmpJid :
|
|
250
|
+ (authenticatedUser? "-" + RandomUtil.randomHexString(6):
|
|
251
|
+ tmpJid.substr(0, 8));
|
|
252
|
+ return this.connection.emuc.createRoom(roomjid, null, options,
|
|
253
|
+ settings);
|
|
254
|
+ }
|
291
|
255
|
|
292
|
|
- roomjid += '/' + tmpJid;
|
|
256
|
+ addListener (type, listener) {
|
|
257
|
+ this.eventEmitter.on(type, listener);
|
293
|
258
|
}
|
294
|
259
|
|
295
|
|
- return this.connection.emuc.createRoom(roomjid, null, options, settings);
|
296
|
|
-}
|
|
260
|
+ removeListener (type, listener) {
|
|
261
|
+ this.eventEmitter.removeListener(type, listener);
|
|
262
|
+ };
|
297
|
263
|
|
298
|
|
-XMPP.prototype.addListener = function(type, listener) {
|
299
|
|
- this.eventEmitter.on(type, listener);
|
300
|
|
-};
|
|
264
|
+ /**
|
|
265
|
+ * Sends 'data' as a log message to the focus. Returns true iff a message
|
|
266
|
+ * was sent.
|
|
267
|
+ * @param data
|
|
268
|
+ * @returns {boolean} true iff a message was sent.
|
|
269
|
+ */
|
|
270
|
+ sendLogs (data) {
|
|
271
|
+ if (!this.connection.emuc.focusMucJid)
|
|
272
|
+ return false;
|
|
273
|
+
|
|
274
|
+ const content = Base64.encode(
|
|
275
|
+ String.fromCharCode.apply(null,
|
|
276
|
+ Pako.deflateRaw(JSON.stringify(data))));
|
|
277
|
+ // XEP-0337-ish
|
|
278
|
+ const message = $msg({
|
|
279
|
+ to: this.connection.emuc.focusMucJid,
|
|
280
|
+ type: "normal"
|
|
281
|
+ });
|
|
282
|
+ message.c("log", {
|
|
283
|
+ xmlns: "urn:xmpp:eventlog",
|
|
284
|
+ id: "PeerConnectionStats"
|
|
285
|
+ });
|
|
286
|
+ message.c("message").t(content).up();
|
|
287
|
+ message.c("tag", {name: "deflated", value: "true"}).up();
|
|
288
|
+ message.up();
|
301
|
289
|
|
302
|
|
-XMPP.prototype.removeListener = function (type, listener) {
|
303
|
|
- this.eventEmitter.removeListener(type, listener);
|
304
|
|
-};
|
|
290
|
+ this.connection.send(message);
|
|
291
|
+ return true;
|
|
292
|
+ }
|
305
|
293
|
|
306
|
|
-/**
|
307
|
|
- * Sends 'data' as a log message to the focus. Returns true iff a message
|
308
|
|
- * was sent.
|
309
|
|
- * @param data
|
310
|
|
- * @returns {boolean} true iff a message was sent.
|
311
|
|
- */
|
312
|
|
-XMPP.prototype.sendLogs = function (data) {
|
313
|
|
- if (!this.connection.emuc.focusMucJid)
|
314
|
|
- return false;
|
315
|
|
-
|
316
|
|
- var deflate = true;
|
317
|
|
-
|
318
|
|
- var content = JSON.stringify(data);
|
319
|
|
- if (deflate) {
|
320
|
|
- content = String.fromCharCode.apply(null, Pako.deflateRaw(content));
|
|
294
|
+ /**
|
|
295
|
+ * Returns the logs from strophe.jingle.
|
|
296
|
+ * @returns {Object}
|
|
297
|
+ */
|
|
298
|
+ getJingleLog () {
|
|
299
|
+ const jingle = this.connection.jingle;
|
|
300
|
+ return jingle? jingle.getLog() : {};
|
321
|
301
|
}
|
322
|
|
- content = Base64.encode(content);
|
323
|
|
- // XEP-0337-ish
|
324
|
|
- var message = $msg({to: this.connection.emuc.focusMucJid, type: 'normal'});
|
325
|
|
- message.c('log', {xmlns: 'urn:xmpp:eventlog', id: 'PeerConnectionStats'});
|
326
|
|
- message.c('message').t(content).up();
|
327
|
|
- if (deflate) {
|
328
|
|
- message.c('tag', {name: "deflated", value: "true"}).up();
|
|
302
|
+
|
|
303
|
+ /**
|
|
304
|
+ * Returns the logs from strophe.
|
|
305
|
+ */
|
|
306
|
+ getXmppLog () {
|
|
307
|
+ return (this.connection.logger || {}).log || null;
|
329
|
308
|
}
|
330
|
|
- message.up();
|
331
|
309
|
|
332
|
|
- this.connection.send(message);
|
333
|
|
- return true;
|
334
|
|
-};
|
|
310
|
+ dial (to, from, roomName,roomPass) {
|
|
311
|
+ this.connection.rayo.dial(to, from, roomName,roomPass);
|
|
312
|
+ }
|
335
|
313
|
|
336
|
|
-// Gets the logs from strophe.jingle.
|
337
|
|
-XMPP.prototype.getJingleLog = function () {
|
338
|
|
- return this.connection.jingle ? this.connection.jingle.getLog() : {};
|
339
|
|
-};
|
|
314
|
+ setMute (jid, mute) {
|
|
315
|
+ this.connection.moderate.setMute(jid, mute);
|
|
316
|
+ }
|
340
|
317
|
|
341
|
|
-// Gets the logs from strophe.
|
342
|
|
-XMPP.prototype.getXmppLog = function () {
|
343
|
|
- return this.connection.logger ? this.connection.logger.log : null;
|
344
|
|
-};
|
|
318
|
+ eject (jid) {
|
|
319
|
+ this.connection.moderate.eject(jid);
|
|
320
|
+ }
|
345
|
321
|
|
346
|
|
-XMPP.prototype.dial = function (to, from, roomName,roomPass) {
|
347
|
|
- this.connection.rayo.dial(to, from, roomName,roomPass);
|
348
|
|
-};
|
|
322
|
+ getSessions () {
|
|
323
|
+ return this.connection.jingle.sessions;
|
|
324
|
+ }
|
349
|
325
|
|
350
|
|
-XMPP.prototype.setMute = function (jid, mute) {
|
351
|
|
- this.connection.moderate.setMute(jid, mute);
|
352
|
|
-};
|
|
326
|
+ /**
|
|
327
|
+ * Disconnects this from the XMPP server (if this is connected).
|
|
328
|
+ *
|
|
329
|
+ * @param ev optionally, the event which triggered the necessity to disconnect
|
|
330
|
+ * from the XMPP server (e.g. beforeunload, unload)
|
|
331
|
+ */
|
|
332
|
+ disconnect (ev) {
|
|
333
|
+ if (this.disconnectInProgress
|
|
334
|
+ || !this.connection
|
|
335
|
+ || !this.connection.connected) {
|
|
336
|
+ this.eventEmitter.emit(JitsiConnectionEvents.WRONG_STATE);
|
|
337
|
+ return;
|
|
338
|
+ }
|
353
|
339
|
|
354
|
|
-XMPP.prototype.eject = function (jid) {
|
355
|
|
- this.connection.moderate.eject(jid);
|
356
|
|
-};
|
|
340
|
+ this.disconnectInProgress = true;
|
|
341
|
+
|
|
342
|
+ // XXX Strophe is asynchronously sending by default. Unfortunately, that
|
|
343
|
+ // means that there may not be enough time to send an unavailable presence
|
|
344
|
+ // or disconnect at all. Switching Strophe to synchronous sending is not
|
|
345
|
+ // much of an option because it may lead to a noticeable delay in navigating
|
|
346
|
+ // away from the current location. As a compromise, we will try to increase
|
|
347
|
+ // the chances of sending an unavailable presence and/or disconecting within
|
|
348
|
+ // the short time span that we have upon unloading by invoking flush() on
|
|
349
|
+ // the connection. We flush() once before disconnect() in order to attemtp
|
|
350
|
+ // to have its unavailable presence at the top of the send queue. We flush()
|
|
351
|
+ // once more after disconnect() in order to attempt to have its unavailable
|
|
352
|
+ // presence sent as soon as possible.
|
|
353
|
+ this.connection.flush();
|
357
|
354
|
|
358
|
|
-XMPP.prototype.getSessions = function () {
|
359
|
|
- return this.connection.jingle.sessions;
|
360
|
|
-};
|
|
355
|
+ if (ev !== null && typeof ev !== 'undefined') {
|
|
356
|
+ const evType = ev.type;
|
|
357
|
+
|
|
358
|
+ if (evType == 'beforeunload' || evType == 'unload') {
|
|
359
|
+ // XXX Whatever we said above, synchronous sending is the best
|
|
360
|
+ // (known) way to properly disconnect from the XMPP server.
|
|
361
|
+ // Consequently, it may be fine to have the source code and comment
|
|
362
|
+ // it in or out depending on whether we want to run with it for some
|
|
363
|
+ // time.
|
|
364
|
+ this.connection.options.sync = true;
|
|
365
|
+ }
|
|
366
|
+ }
|
361
|
367
|
|
362
|
|
-/**
|
363
|
|
- * Disconnects this from the XMPP server (if this is connected).
|
364
|
|
- *
|
365
|
|
- * @param ev optionally, the event which triggered the necessity to disconnect
|
366
|
|
- * from the XMPP server (e.g. beforeunload, unload)
|
367
|
|
- */
|
368
|
|
-XMPP.prototype.disconnect = function (ev) {
|
369
|
|
- if (this.disconnectInProgress
|
370
|
|
- || !this.connection
|
371
|
|
- || !this.connection.connected) {
|
372
|
|
- this.eventEmitter.emit(JitsiConnectionEvents.WRONG_STATE);
|
373
|
|
- return;
|
374
|
|
- }
|
|
368
|
+ this.connection.disconnect();
|
375
|
369
|
|
376
|
|
- this.disconnectInProgress = true;
|
377
|
|
-
|
378
|
|
- // XXX Strophe is asynchronously sending by default. Unfortunately, that
|
379
|
|
- // means that there may not be enough time to send an unavailable presence
|
380
|
|
- // or disconnect at all. Switching Strophe to synchronous sending is not
|
381
|
|
- // much of an option because it may lead to a noticeable delay in navigating
|
382
|
|
- // away from the current location. As a compromise, we will try to increase
|
383
|
|
- // the chances of sending an unavailable presence and/or disconecting within
|
384
|
|
- // the short time span that we have upon unloading by invoking flush() on
|
385
|
|
- // the connection. We flush() once before disconnect() in order to attemtp
|
386
|
|
- // to have its unavailable presence at the top of the send queue. We flush()
|
387
|
|
- // once more after disconnect() in order to attempt to have its unavailable
|
388
|
|
- // presence sent as soon as possible.
|
389
|
|
- this.connection.flush();
|
390
|
|
-
|
391
|
|
- if (ev !== null && typeof ev !== 'undefined') {
|
392
|
|
- var evType = ev.type;
|
393
|
|
-
|
394
|
|
- if (evType == 'beforeunload' || evType == 'unload') {
|
395
|
|
- // XXX Whatever we said above, synchronous sending is the best
|
396
|
|
- // (known) way to properly disconnect from the XMPP server.
|
397
|
|
- // Consequently, it may be fine to have the source code and comment
|
398
|
|
- // it in or out depending on whether we want to run with it for some
|
399
|
|
- // time.
|
400
|
|
- this.connection.options.sync = true;
|
|
370
|
+ if (this.connection.options.sync !== true) {
|
|
371
|
+ this.connection.flush();
|
401
|
372
|
}
|
402
|
373
|
}
|
403
|
374
|
|
404
|
|
- this.connection.disconnect();
|
405
|
|
-
|
406
|
|
- if (this.connection.options.sync !== true) {
|
407
|
|
- this.connection.flush();
|
|
375
|
+ _initStrophePlugins() {
|
|
376
|
+ initEmuc(this);
|
|
377
|
+ initJingle(this, this.eventEmitter);
|
|
378
|
+ initStropheUtil();
|
|
379
|
+ initPing(this, this.eventEmitter);
|
|
380
|
+ initRayo();
|
|
381
|
+ initStropheLogger();
|
408
|
382
|
}
|
409
|
|
-};
|
410
|
|
-
|
411
|
|
-module.exports = XMPP;
|
|
383
|
+}
|