2015-09-11 03:05:53 +00:00
|
|
|
|
/* global $, APP, config, Strophe, Base64, $msg */
|
2015-09-11 02:42:15 +00:00
|
|
|
|
/* jshint -W101 */
|
2015-01-19 09:20:00 +00:00
|
|
|
|
var Moderator = require("./moderator");
|
|
|
|
|
var EventEmitter = require("events");
|
|
|
|
|
var Recording = require("./recording");
|
|
|
|
|
var SDP = require("./SDP");
|
2015-09-02 09:56:22 +00:00
|
|
|
|
var SDPUtil = require("./SDPUtil");
|
2015-03-25 11:39:22 +00:00
|
|
|
|
var Settings = require("../settings/Settings");
|
2015-01-21 15:13:13 +00:00
|
|
|
|
var Pako = require("pako");
|
2015-01-28 14:35:22 +00:00
|
|
|
|
var StreamEventTypes = require("../../service/RTC/StreamEventTypes");
|
2015-03-27 09:36:39 +00:00
|
|
|
|
var RTCEvents = require("../../service/RTC/RTCEvents");
|
2015-01-28 14:35:22 +00:00
|
|
|
|
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
|
2015-04-22 20:31:18 +00:00
|
|
|
|
var retry = require('retry');
|
2015-11-03 19:21:25 +00:00
|
|
|
|
var RandomUtil = require("../util/RandomUtil");
|
2015-01-19 09:20:00 +00:00
|
|
|
|
|
|
|
|
|
var eventEmitter = new EventEmitter();
|
|
|
|
|
var connection = null;
|
|
|
|
|
var authenticatedUser = false;
|
|
|
|
|
|
2015-11-03 19:21:25 +00:00
|
|
|
|
/**
|
|
|
|
|
* Utility method that generates user name based on random hex values.
|
|
|
|
|
* Eg. 12345678-1234-1234-12345678
|
|
|
|
|
* @returns {string}
|
|
|
|
|
*/
|
|
|
|
|
function generateUserName() {
|
2015-11-06 00:51:23 +00:00
|
|
|
|
return RandomUtil.randomHexString(8) + "-" + RandomUtil.randomHexString(4)
|
|
|
|
|
+ "-" + RandomUtil.randomHexString(4) + "-"
|
|
|
|
|
+ RandomUtil.randomHexString(8);
|
2015-11-03 19:21:25 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-03-09 15:16:06 +00:00
|
|
|
|
function connect(jid, password) {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
|
2015-04-22 20:31:18 +00:00
|
|
|
|
var faultTolerantConnect = retry.operation({
|
|
|
|
|
retries: 3
|
|
|
|
|
});
|
2015-01-19 09:20:00 +00:00
|
|
|
|
|
2015-04-22 20:31:18 +00:00
|
|
|
|
// fault tolerant connect
|
|
|
|
|
faultTolerantConnect.attempt(function () {
|
|
|
|
|
|
|
|
|
|
connection = XMPP.createConnection();
|
|
|
|
|
Moderator.setConnection(connection);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
|
2015-04-22 20:31:18 +00:00
|
|
|
|
connection.jingle.pc_constraints = APP.RTC.getPCConstraints();
|
|
|
|
|
if (config.useIPv6) {
|
|
|
|
|
// https://code.google.com/p/webrtc/issues/detail?id=2828
|
|
|
|
|
if (!connection.jingle.pc_constraints.optional)
|
|
|
|
|
connection.jingle.pc_constraints.optional = [];
|
|
|
|
|
connection.jingle.pc_constraints.optional.push({googIPv6: true});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Include user info in MUC presence
|
|
|
|
|
var settings = Settings.getSettings();
|
|
|
|
|
if (settings.email) {
|
|
|
|
|
connection.emuc.addEmailToPresence(settings.email);
|
|
|
|
|
}
|
|
|
|
|
if (settings.uid) {
|
|
|
|
|
connection.emuc.addUserIdToPresence(settings.uid);
|
|
|
|
|
}
|
|
|
|
|
if (settings.displayName) {
|
|
|
|
|
connection.emuc.addDisplayNameToPresence(settings.displayName);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
}
|
2015-04-22 20:31:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// connection.connect() starts the connection process.
|
|
|
|
|
//
|
|
|
|
|
// As the connection process proceeds, the user supplied callback will
|
|
|
|
|
// be triggered multiple times with status updates. The callback should
|
|
|
|
|
// take two arguments - the status code and the error condition.
|
|
|
|
|
//
|
|
|
|
|
// The status code will be one of the values in the Strophe.Status
|
|
|
|
|
// constants. The error condition will be one of the conditions defined
|
|
|
|
|
// in RFC 3920 or the condition ‘strophe-parsererror’.
|
|
|
|
|
//
|
|
|
|
|
// The Parameters wait, hold and route are optional and only relevant
|
|
|
|
|
// for BOSH connections. Please see XEP 124 for a more detailed
|
|
|
|
|
// explanation of the optional parameters.
|
|
|
|
|
//
|
|
|
|
|
// Connection status constants for use by the connection handler
|
|
|
|
|
// callback.
|
|
|
|
|
//
|
|
|
|
|
// Status.ERROR - An error has occurred (websockets specific)
|
|
|
|
|
// Status.CONNECTING - The connection is currently being made
|
|
|
|
|
// Status.CONNFAIL - The connection attempt failed
|
|
|
|
|
// Status.AUTHENTICATING - The connection is authenticating
|
|
|
|
|
// Status.AUTHFAIL - The authentication attempt failed
|
|
|
|
|
// Status.CONNECTED - The connection has succeeded
|
|
|
|
|
// Status.DISCONNECTED - The connection has been terminated
|
|
|
|
|
// Status.DISCONNECTING - The connection is currently being terminated
|
|
|
|
|
// Status.ATTACHED - The connection has been attached
|
|
|
|
|
|
|
|
|
|
var anonymousConnectionFailed = false;
|
|
|
|
|
var connectionFailed = false;
|
|
|
|
|
var lastErrorMsg;
|
|
|
|
|
connection.connect(jid, password, function (status, msg) {
|
2015-10-06 21:36:41 +00:00
|
|
|
|
console.log("(TIME) Strophe " + Strophe.getStatusString(status) +
|
|
|
|
|
(msg ? "[" + msg + "]" : "") +
|
|
|
|
|
"\t:" + window.performance.now());
|
2015-04-22 20:31:18 +00:00
|
|
|
|
if (status === Strophe.Status.CONNECTED) {
|
|
|
|
|
if (config.useStunTurn) {
|
|
|
|
|
connection.jingle.getStunAndTurnCredentials();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.info("My Jabber ID: " + connection.jid);
|
|
|
|
|
|
2015-08-28 09:25:42 +00:00
|
|
|
|
// Schedule ping ?
|
2015-08-28 09:30:42 +00:00
|
|
|
|
var pingJid = connection.domain;
|
2015-08-28 09:25:42 +00:00
|
|
|
|
connection.ping.hasPingSupport(
|
|
|
|
|
pingJid,
|
|
|
|
|
function (hasPing) {
|
|
|
|
|
if (hasPing)
|
|
|
|
|
connection.ping.startInterval(pingJid);
|
|
|
|
|
else
|
|
|
|
|
console.warn("Ping NOT supported by " + pingJid);
|
|
|
|
|
}
|
|
|
|
|
);
|
2015-08-25 08:25:45 +00:00
|
|
|
|
|
2015-04-22 20:31:18 +00:00
|
|
|
|
if (password)
|
|
|
|
|
authenticatedUser = true;
|
|
|
|
|
maybeDoJoin();
|
|
|
|
|
} else if (status === Strophe.Status.CONNFAIL) {
|
|
|
|
|
if (msg === 'x-strophe-bad-non-anon-jid') {
|
|
|
|
|
anonymousConnectionFailed = true;
|
|
|
|
|
} else {
|
|
|
|
|
connectionFailed = true;
|
|
|
|
|
}
|
|
|
|
|
lastErrorMsg = msg;
|
|
|
|
|
} else if (status === Strophe.Status.DISCONNECTED) {
|
2015-08-25 08:25:45 +00:00
|
|
|
|
// Stop ping interval
|
|
|
|
|
connection.ping.stopInterval();
|
2015-04-22 20:31:18 +00:00
|
|
|
|
if (anonymousConnectionFailed) {
|
|
|
|
|
// prompt user for username and password
|
|
|
|
|
XMPP.promptLogin();
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
|
|
// Strophe already has built-in HTTP/BOSH error handling and
|
|
|
|
|
// request retry logic. Requests are resent automatically
|
|
|
|
|
// until their error count reaches 5. Strophe.js disconnects
|
|
|
|
|
// if the error count is > 5. We are not replicating this
|
|
|
|
|
// here.
|
|
|
|
|
//
|
|
|
|
|
// The "problem" is that failed HTTP/BOSH requests don't
|
|
|
|
|
// trigger a callback with a status update, so when a
|
|
|
|
|
// callback with status Strophe.Status.DISCONNECTED arrives,
|
|
|
|
|
// we can't be sure if it's a graceful disconnect or if it's
|
|
|
|
|
// triggered by some HTTP/BOSH error.
|
|
|
|
|
//
|
|
|
|
|
// But that's a minor issue in Jitsi Meet as we never
|
|
|
|
|
// disconnect anyway, not even when the user closes the
|
|
|
|
|
// browser window (which is kind of wrong, but the point is
|
|
|
|
|
// that we should never ever get disconnected).
|
|
|
|
|
//
|
|
|
|
|
// On the other hand, failed connections due to XMPP layer
|
|
|
|
|
// errors, trigger a callback with status Strophe.Status.CONNFAIL.
|
|
|
|
|
//
|
|
|
|
|
// Here we implement retry logic for failed connections due
|
|
|
|
|
// to XMPP layer errors and we display an error to the user
|
|
|
|
|
// if we get disconnected from the XMPP server permanently.
|
|
|
|
|
|
|
|
|
|
// If the connection failed, retry.
|
2015-07-22 18:34:44 +00:00
|
|
|
|
if (connectionFailed &&
|
|
|
|
|
faultTolerantConnect.retry("connection-failed")) {
|
2015-04-22 20:31:18 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If we failed to connect to the XMPP server, fire an event
|
|
|
|
|
// to let all the interested module now about it.
|
|
|
|
|
eventEmitter.emit(XMPPEvents.CONNECTION_FAILED,
|
|
|
|
|
msg ? msg : lastErrorMsg);
|
|
|
|
|
}
|
|
|
|
|
} else if (status === Strophe.Status.AUTHFAIL) {
|
|
|
|
|
// wrong password or username, prompt user
|
|
|
|
|
XMPP.promptLogin();
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
});
|
2015-01-19 09:20:00 +00:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function maybeDoJoin() {
|
|
|
|
|
if (connection && connection.connected &&
|
2015-07-22 18:34:44 +00:00
|
|
|
|
Strophe.getResourceFromJid(connection.jid) &&
|
|
|
|
|
(APP.RTC.localAudio || APP.RTC.localVideo)) {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
// .connected is true while connecting?
|
|
|
|
|
doJoin();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function doJoin() {
|
2015-06-18 17:49:43 +00:00
|
|
|
|
eventEmitter.emit(XMPPEvents.READY_TO_JOIN);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function initStrophePlugins()
|
|
|
|
|
{
|
|
|
|
|
require("./strophe.emuc")(XMPP, eventEmitter);
|
2015-01-24 14:28:02 +00:00
|
|
|
|
require("./strophe.jingle")(XMPP, eventEmitter);
|
2015-06-18 17:49:43 +00:00
|
|
|
|
require("./strophe.moderate")(XMPP, eventEmitter);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
require("./strophe.util")();
|
2015-08-25 10:11:31 +00:00
|
|
|
|
require("./strophe.ping")(XMPP, eventEmitter);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
require("./strophe.rayo")();
|
|
|
|
|
require("./strophe.logger")();
|
|
|
|
|
}
|
|
|
|
|
|
2015-08-05 12:09:12 +00:00
|
|
|
|
/**
|
|
|
|
|
* If given <tt>localStream</tt> is video one this method will advertise it's
|
|
|
|
|
* video type in MUC presence.
|
|
|
|
|
* @param localStream new or modified <tt>LocalStream</tt>.
|
|
|
|
|
*/
|
|
|
|
|
function broadcastLocalVideoType(localStream) {
|
|
|
|
|
if (localStream.videoType)
|
|
|
|
|
XMPP.addToPresence('videoType', localStream.videoType);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-19 09:20:00 +00:00
|
|
|
|
function registerListeners() {
|
2015-08-05 12:09:12 +00:00
|
|
|
|
APP.RTC.addStreamListener(
|
|
|
|
|
function (localStream) {
|
|
|
|
|
maybeDoJoin();
|
|
|
|
|
broadcastLocalVideoType(localStream);
|
|
|
|
|
},
|
|
|
|
|
StreamEventTypes.EVENT_TYPE_LOCAL_CREATED
|
|
|
|
|
);
|
|
|
|
|
APP.RTC.addStreamListener(
|
|
|
|
|
broadcastLocalVideoType,
|
|
|
|
|
StreamEventTypes.EVENT_TYPE_LOCAL_CHANGED
|
|
|
|
|
);
|
2015-03-27 09:36:39 +00:00
|
|
|
|
APP.RTC.addListener(RTCEvents.AVAILABLE_DEVICES_CHANGED, function (devices) {
|
|
|
|
|
XMPP.addToPresence("devices", devices);
|
2015-01-24 14:28:02 +00:00
|
|
|
|
});
|
2015-01-19 09:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-20 08:44:32 +00:00
|
|
|
|
var unload = (function () {
|
|
|
|
|
var unloaded = false;
|
|
|
|
|
|
|
|
|
|
return function () {
|
|
|
|
|
if (unloaded) { return; }
|
|
|
|
|
unloaded = true;
|
|
|
|
|
|
2015-01-19 09:20:00 +00:00
|
|
|
|
if (connection && connection.connected) {
|
|
|
|
|
// ensure signout
|
|
|
|
|
$.ajax({
|
|
|
|
|
type: 'POST',
|
|
|
|
|
url: config.bosh,
|
|
|
|
|
async: false,
|
|
|
|
|
cache: false,
|
|
|
|
|
contentType: 'application/xml',
|
2015-07-22 18:34:44 +00:00
|
|
|
|
data: "<body rid='" +
|
|
|
|
|
(connection.rid || connection._proto.rid) +
|
2015-05-20 08:44:32 +00:00
|
|
|
|
"' xmlns='http://jabber.org/protocol/httpbind' sid='" +
|
|
|
|
|
(connection.sid || connection._proto.sid) +
|
|
|
|
|
"' type='terminate'>" +
|
|
|
|
|
"<presence xmlns='jabber:client' type='unavailable'/>" +
|
|
|
|
|
"</body>",
|
2015-01-19 09:20:00 +00:00
|
|
|
|
success: function (data) {
|
|
|
|
|
console.log('signed out');
|
|
|
|
|
console.log(data);
|
|
|
|
|
},
|
|
|
|
|
error: function (XMLHttpRequest, textStatus, errorThrown) {
|
|
|
|
|
console.log('signout error',
|
2015-05-20 08:44:32 +00:00
|
|
|
|
textStatus + ' (' + errorThrown + ')');
|
2015-01-19 09:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
XMPP.disposeConference(true);
|
2015-05-20 08:44:32 +00:00
|
|
|
|
};
|
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
function setupEvents() {
|
|
|
|
|
// In recent versions of FF the 'beforeunload' event is not fired when the
|
|
|
|
|
// window or the tab is closed. It is only fired when we leave the page
|
|
|
|
|
// (change URL). If this participant doesn't unload properly, then it
|
|
|
|
|
// becomes a ghost for the rest of the participants that stay in the
|
|
|
|
|
// conference. Thankfully handling the 'unload' event in addition to the
|
2015-07-22 18:34:44 +00:00
|
|
|
|
// 'beforeunload' event seems to guarantee the execution of the 'unload'
|
2015-05-20 08:44:32 +00:00
|
|
|
|
// method at least once.
|
|
|
|
|
//
|
|
|
|
|
// The 'unload' method can safely be run multiple times, it will actually do
|
|
|
|
|
// something only the first time that it's run, so we're don't have to worry
|
|
|
|
|
// about browsers that fire both events.
|
|
|
|
|
|
|
|
|
|
$(window).bind('beforeunload', unload);
|
|
|
|
|
$(window).bind('unload', unload);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var XMPP = {
|
2015-04-07 16:01:19 +00:00
|
|
|
|
getConnection: function(){ return connection; },
|
2015-01-19 09:20:00 +00:00
|
|
|
|
sessionTerminated: false,
|
2015-03-13 14:01:42 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* XMPP connection status
|
|
|
|
|
*/
|
|
|
|
|
Status: Strophe.Status,
|
|
|
|
|
|
2015-01-19 09:20:00 +00:00
|
|
|
|
/**
|
|
|
|
|
* Remembers if we were muted by the focus.
|
|
|
|
|
* @type {boolean}
|
|
|
|
|
*/
|
|
|
|
|
forceMuted: false,
|
2015-03-09 15:16:06 +00:00
|
|
|
|
start: function () {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
setupEvents();
|
|
|
|
|
initStrophePlugins();
|
|
|
|
|
registerListeners();
|
2015-01-29 09:09:09 +00:00
|
|
|
|
Moderator.init(this, eventEmitter);
|
2015-08-21 12:33:05 +00:00
|
|
|
|
Recording.init();
|
2015-01-19 10:00:30 +00:00
|
|
|
|
var configDomain = config.hosts.anonymousdomain || config.hosts.domain;
|
|
|
|
|
// Force authenticated domain if room is appended with '?login=true'
|
|
|
|
|
if (config.hosts.anonymousdomain &&
|
|
|
|
|
window.location.search.indexOf("login=true") !== -1) {
|
|
|
|
|
configDomain = config.hosts.domain;
|
|
|
|
|
}
|
2015-03-09 15:16:06 +00:00
|
|
|
|
var jid = configDomain || window.location.hostname;
|
2015-11-03 19:21:25 +00:00
|
|
|
|
var password = null;
|
|
|
|
|
if (config.token) {
|
|
|
|
|
password = config.token;
|
|
|
|
|
if (config.id) {
|
|
|
|
|
jid = config.id + "@" + jid;
|
|
|
|
|
} else {
|
|
|
|
|
jid = generateUserName() + "@" + jid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
connect(jid, password);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
},
|
2015-03-13 14:01:42 +00:00
|
|
|
|
createConnection: function () {
|
|
|
|
|
var bosh = config.bosh || '/http-bind';
|
2015-11-03 20:32:25 +00:00
|
|
|
|
// adds the room name used to the bosh connection
|
|
|
|
|
return new Strophe.Connection(bosh + '?ROOM=' + APP.UI.getRoomNode());
|
2015-03-13 14:01:42 +00:00
|
|
|
|
},
|
|
|
|
|
getStatusString: function (status) {
|
|
|
|
|
return Strophe.getStatusString(status);
|
|
|
|
|
},
|
2015-01-19 09:20:00 +00:00
|
|
|
|
promptLogin: function () {
|
2015-09-14 21:06:58 +00:00
|
|
|
|
eventEmitter.emit(XMPPEvents.PROMPT_FOR_LOGIN, connect);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
},
|
2015-07-22 18:34:44 +00:00
|
|
|
|
joinRoom: function(roomName, useNicks, nick) {
|
|
|
|
|
var roomjid = roomName;
|
2015-01-19 09:20:00 +00:00
|
|
|
|
|
|
|
|
|
if (useNicks) {
|
|
|
|
|
if (nick) {
|
|
|
|
|
roomjid += '/' + nick;
|
|
|
|
|
} else {
|
|
|
|
|
roomjid += '/' + Strophe.getNodeFromJid(connection.jid);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
var tmpJid = Strophe.getNodeFromJid(connection.jid);
|
|
|
|
|
|
|
|
|
|
if(!authenticatedUser)
|
|
|
|
|
tmpJid = tmpJid.substr(0, 8);
|
|
|
|
|
|
|
|
|
|
roomjid += '/' + tmpJid;
|
|
|
|
|
}
|
|
|
|
|
connection.emuc.doJoin(roomjid);
|
|
|
|
|
},
|
|
|
|
|
myJid: function () {
|
|
|
|
|
if(!connection)
|
|
|
|
|
return null;
|
|
|
|
|
return connection.emuc.myroomjid;
|
|
|
|
|
},
|
|
|
|
|
myResource: function () {
|
|
|
|
|
if(!connection || ! connection.emuc.myroomjid)
|
|
|
|
|
return null;
|
|
|
|
|
return Strophe.getResourceFromJid(connection.emuc.myroomjid);
|
|
|
|
|
},
|
2015-09-02 21:05:00 +00:00
|
|
|
|
getLastPresence: function (from) {
|
|
|
|
|
if(!connection)
|
|
|
|
|
return null;
|
|
|
|
|
return connection.emuc.lastPresenceMap[from];
|
|
|
|
|
},
|
2015-01-19 09:20:00 +00:00
|
|
|
|
disposeConference: function (onUnload) {
|
2015-01-19 16:54:41 +00:00
|
|
|
|
var handler = connection.jingle.activecall;
|
2015-01-19 09:20:00 +00:00
|
|
|
|
if (handler && handler.peerconnection) {
|
|
|
|
|
// FIXME: probably removing streams is not required and close() should
|
|
|
|
|
// be enough
|
2015-01-28 14:35:22 +00:00
|
|
|
|
if (APP.RTC.localAudio) {
|
2015-03-23 16:12:24 +00:00
|
|
|
|
handler.peerconnection.removeStream(
|
|
|
|
|
APP.RTC.localAudio.getOriginalStream(), onUnload);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
}
|
2015-01-28 14:35:22 +00:00
|
|
|
|
if (APP.RTC.localVideo) {
|
2015-03-23 16:12:24 +00:00
|
|
|
|
handler.peerconnection.removeStream(
|
|
|
|
|
APP.RTC.localVideo.getOriginalStream(), onUnload);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
handler.peerconnection.close();
|
|
|
|
|
}
|
2015-06-26 12:32:40 +00:00
|
|
|
|
eventEmitter.emit(XMPPEvents.DISPOSE_CONFERENCE, onUnload);
|
2015-01-19 16:54:41 +00:00
|
|
|
|
connection.jingle.activecall = null;
|
2015-07-22 18:34:44 +00:00
|
|
|
|
if (!onUnload) {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
this.sessionTerminated = true;
|
|
|
|
|
connection.emuc.doLeave();
|
|
|
|
|
}
|
|
|
|
|
},
|
2015-07-22 18:34:44 +00:00
|
|
|
|
addListener: function(type, listener) {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
eventEmitter.on(type, listener);
|
|
|
|
|
},
|
|
|
|
|
removeListener: function (type, listener) {
|
|
|
|
|
eventEmitter.removeListener(type, listener);
|
|
|
|
|
},
|
|
|
|
|
allocateConferenceFocus: function(roomName, callback) {
|
|
|
|
|
Moderator.allocateConferenceFocus(roomName, callback);
|
|
|
|
|
},
|
2015-02-18 15:50:47 +00:00
|
|
|
|
getLoginUrl: function (roomName, callback) {
|
|
|
|
|
Moderator.getLoginUrl(roomName, callback);
|
|
|
|
|
},
|
|
|
|
|
getPopupLoginUrl: function (roomName, callback) {
|
|
|
|
|
Moderator.getPopupLoginUrl(roomName, callback);
|
|
|
|
|
},
|
2015-01-19 09:20:00 +00:00
|
|
|
|
isModerator: function () {
|
|
|
|
|
return Moderator.isModerator();
|
|
|
|
|
},
|
|
|
|
|
isSipGatewayEnabled: function () {
|
|
|
|
|
return Moderator.isSipGatewayEnabled();
|
|
|
|
|
},
|
|
|
|
|
isExternalAuthEnabled: function () {
|
|
|
|
|
return Moderator.isExternalAuthEnabled();
|
|
|
|
|
},
|
2015-07-09 13:04:08 +00:00
|
|
|
|
isConferenceInProgress: function () {
|
|
|
|
|
return connection && connection.jingle.activecall &&
|
|
|
|
|
connection.jingle.activecall.peerconnection;
|
|
|
|
|
},
|
2015-04-22 09:31:08 +00:00
|
|
|
|
switchStreams: function (stream, oldStream, callback, isAudio) {
|
2015-07-09 13:04:08 +00:00
|
|
|
|
if (this.isConferenceInProgress()) {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
// FIXME: will block switchInProgress on true value in case of exception
|
2015-04-22 09:31:08 +00:00
|
|
|
|
connection.jingle.activecall.switchStreams(stream, oldStream, callback, isAudio);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
} else {
|
|
|
|
|
// We are done immediately
|
2015-03-04 12:56:45 +00:00
|
|
|
|
console.warn("No conference handler or conference not started yet");
|
2015-01-19 09:20:00 +00:00
|
|
|
|
callback();
|
|
|
|
|
}
|
|
|
|
|
},
|
2015-03-23 16:12:24 +00:00
|
|
|
|
sendVideoInfoPresence: function (mute) {
|
2015-04-22 09:31:08 +00:00
|
|
|
|
if(!connection)
|
|
|
|
|
return;
|
2015-03-23 16:12:24 +00:00
|
|
|
|
connection.emuc.addVideoInfoToPresence(mute);
|
|
|
|
|
connection.emuc.sendPresence();
|
|
|
|
|
},
|
2015-01-19 09:20:00 +00:00
|
|
|
|
setVideoMute: function (mute, callback, options) {
|
2015-03-23 16:12:24 +00:00
|
|
|
|
if(!connection)
|
2015-03-18 16:41:41 +00:00
|
|
|
|
return;
|
2015-03-23 16:12:24 +00:00
|
|
|
|
var self = this;
|
2015-03-18 16:41:41 +00:00
|
|
|
|
var localCallback = function (mute) {
|
2015-03-23 16:12:24 +00:00
|
|
|
|
self.sendVideoInfoPresence(mute);
|
2015-03-18 16:41:41 +00:00
|
|
|
|
return callback(mute);
|
|
|
|
|
};
|
|
|
|
|
|
2015-03-23 16:12:24 +00:00
|
|
|
|
if(connection.jingle.activecall)
|
2015-03-18 16:41:41 +00:00
|
|
|
|
{
|
2015-03-23 16:12:24 +00:00
|
|
|
|
connection.jingle.activecall.setVideoMute(
|
|
|
|
|
mute, localCallback, options);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
localCallback(mute);
|
2015-03-18 16:41:41 +00:00
|
|
|
|
}
|
2015-03-23 16:12:24 +00:00
|
|
|
|
|
2015-01-19 09:20:00 +00:00
|
|
|
|
},
|
|
|
|
|
setAudioMute: function (mute, callback) {
|
2015-01-28 14:35:22 +00:00
|
|
|
|
if (!(connection && APP.RTC.localAudio)) {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.forceMuted && !mute) {
|
|
|
|
|
console.info("Asking focus for unmute");
|
|
|
|
|
connection.moderate.setMute(connection.emuc.myroomjid, mute);
|
|
|
|
|
// FIXME: wait for result before resetting muted status
|
|
|
|
|
this.forceMuted = false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-28 14:35:22 +00:00
|
|
|
|
if (mute == APP.RTC.localAudio.isMuted()) {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
// Nothing to do
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2015-07-30 19:24:44 +00:00
|
|
|
|
APP.RTC.localAudio.setMute(mute);
|
2015-04-22 09:31:08 +00:00
|
|
|
|
this.sendAudioInfoPresence(mute, callback);
|
|
|
|
|
return true;
|
|
|
|
|
},
|
2015-07-22 20:02:44 +00:00
|
|
|
|
sendAudioInfoPresence: function(mute, callback) {
|
2015-04-22 09:31:08 +00:00
|
|
|
|
if(connection) {
|
|
|
|
|
connection.emuc.addAudioInfoToPresence(mute);
|
|
|
|
|
connection.emuc.sendPresence();
|
|
|
|
|
}
|
2015-01-19 09:20:00 +00:00
|
|
|
|
callback();
|
|
|
|
|
return true;
|
|
|
|
|
},
|
|
|
|
|
toggleRecording: function (tokenEmptyCallback,
|
2015-08-06 03:18:45 +00:00
|
|
|
|
recordingStateChangeCallback) {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
Recording.toggleRecording(tokenEmptyCallback,
|
2015-08-06 03:18:45 +00:00
|
|
|
|
recordingStateChangeCallback, connection);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
},
|
|
|
|
|
addToPresence: function (name, value, dontSend) {
|
2015-07-22 18:34:44 +00:00
|
|
|
|
switch (name) {
|
2015-01-19 09:20:00 +00:00
|
|
|
|
case "displayName":
|
|
|
|
|
connection.emuc.addDisplayNameToPresence(value);
|
|
|
|
|
break;
|
|
|
|
|
case "prezi":
|
|
|
|
|
connection.emuc.addPreziToPresence(value, 0);
|
|
|
|
|
break;
|
|
|
|
|
case "preziSlide":
|
|
|
|
|
connection.emuc.addCurrentSlideToPresence(value);
|
|
|
|
|
break;
|
|
|
|
|
case "connectionQuality":
|
|
|
|
|
connection.emuc.addConnectionInfoToPresence(value);
|
|
|
|
|
break;
|
|
|
|
|
case "email":
|
|
|
|
|
connection.emuc.addEmailToPresence(value);
|
2015-03-25 11:39:22 +00:00
|
|
|
|
break;
|
2015-03-27 09:36:39 +00:00
|
|
|
|
case "devices":
|
|
|
|
|
connection.emuc.addDevicesToPresence(value);
|
|
|
|
|
break;
|
2015-08-05 12:09:12 +00:00
|
|
|
|
case "videoType":
|
|
|
|
|
connection.emuc.addVideoTypeToPresence(value);
|
|
|
|
|
break;
|
2015-05-19 15:03:01 +00:00
|
|
|
|
case "startMuted":
|
|
|
|
|
if(!Moderator.isModerator())
|
|
|
|
|
return;
|
|
|
|
|
connection.emuc.addStartMutedToPresence(value[0],
|
|
|
|
|
value[1]);
|
|
|
|
|
break;
|
2015-01-19 09:20:00 +00:00
|
|
|
|
default :
|
2015-03-25 11:39:22 +00:00
|
|
|
|
console.log("Unknown tag for presence: " + name);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
2015-03-25 11:39:22 +00:00
|
|
|
|
if (!dontSend)
|
2015-01-19 09:20:00 +00:00
|
|
|
|
connection.emuc.sendPresence();
|
|
|
|
|
},
|
2015-02-26 09:03:29 +00:00
|
|
|
|
/**
|
|
|
|
|
* Sends 'data' as a log message to the focus. Returns true iff a message
|
|
|
|
|
* was sent.
|
|
|
|
|
* @param data
|
|
|
|
|
* @returns {boolean} true iff a message was sent.
|
|
|
|
|
*/
|
2015-01-19 09:20:00 +00:00
|
|
|
|
sendLogs: function (data) {
|
2015-01-20 15:56:00 +00:00
|
|
|
|
if(!connection.emuc.focusMucJid)
|
2015-02-26 09:03:29 +00:00
|
|
|
|
return false;
|
2015-01-19 09:20:00 +00:00
|
|
|
|
|
|
|
|
|
var deflate = true;
|
|
|
|
|
|
2015-01-19 10:00:30 +00:00
|
|
|
|
var content = JSON.stringify(data);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
if (deflate) {
|
2015-01-21 15:35:23 +00:00
|
|
|
|
content = String.fromCharCode.apply(null, Pako.deflateRaw(content));
|
2015-01-19 09:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
content = Base64.encode(content);
|
|
|
|
|
// XEP-0337-ish
|
2015-01-20 15:56:00 +00:00
|
|
|
|
var message = $msg({to: connection.emuc.focusMucJid, type: 'normal'});
|
2015-01-19 09:20:00 +00:00
|
|
|
|
message.c('log', { xmlns: 'urn:xmpp:eventlog',
|
|
|
|
|
id: 'PeerConnectionStats'});
|
|
|
|
|
message.c('message').t(content).up();
|
|
|
|
|
if (deflate) {
|
|
|
|
|
message.c('tag', {name: "deflated", value: "true"}).up();
|
|
|
|
|
}
|
|
|
|
|
message.up();
|
|
|
|
|
|
|
|
|
|
connection.send(message);
|
2015-02-26 09:03:29 +00:00
|
|
|
|
return true;
|
2015-01-19 09:20:00 +00:00
|
|
|
|
},
|
2015-07-22 20:30:42 +00:00
|
|
|
|
// Gets the logs from strophe.jingle.
|
|
|
|
|
getJingleLog: function () {
|
|
|
|
|
return connection.jingle ? connection.jingle.getLog() : {};
|
2015-01-19 09:20:00 +00:00
|
|
|
|
},
|
2015-07-22 20:30:42 +00:00
|
|
|
|
// Gets the logs from strophe.
|
|
|
|
|
getXmppLog: function () {
|
|
|
|
|
return connection.logger ? connection.logger.log : null;
|
2015-01-19 09:20:00 +00:00
|
|
|
|
},
|
|
|
|
|
getPrezi: function () {
|
|
|
|
|
return connection.emuc.getPrezi(this.myJid());
|
|
|
|
|
},
|
|
|
|
|
removePreziFromPresence: function () {
|
|
|
|
|
connection.emuc.removePreziFromPresence();
|
|
|
|
|
connection.emuc.sendPresence();
|
|
|
|
|
},
|
|
|
|
|
sendChatMessage: function (message, nickname) {
|
|
|
|
|
connection.emuc.sendMessage(message, nickname);
|
|
|
|
|
},
|
|
|
|
|
setSubject: function (topic) {
|
|
|
|
|
connection.emuc.setSubject(topic);
|
|
|
|
|
},
|
|
|
|
|
lockRoom: function (key, onSuccess, onError, onNotSupported) {
|
|
|
|
|
connection.emuc.lockRoom(key, onSuccess, onError, onNotSupported);
|
|
|
|
|
},
|
|
|
|
|
dial: function (to, from, roomName,roomPass) {
|
|
|
|
|
connection.rayo.dial(to, from, roomName,roomPass);
|
|
|
|
|
},
|
|
|
|
|
setMute: function (jid, mute) {
|
|
|
|
|
connection.moderate.setMute(jid, mute);
|
|
|
|
|
},
|
|
|
|
|
eject: function (jid) {
|
|
|
|
|
connection.moderate.eject(jid);
|
|
|
|
|
},
|
2015-02-18 15:50:47 +00:00
|
|
|
|
logout: function (callback) {
|
|
|
|
|
Moderator.logout(callback);
|
|
|
|
|
},
|
2015-01-19 09:20:00 +00:00
|
|
|
|
findJidFromResource: function (resource) {
|
2015-01-19 16:54:41 +00:00
|
|
|
|
return connection.emuc.findJidFromResource(resource);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
},
|
|
|
|
|
getMembers: function () {
|
|
|
|
|
return connection.emuc.members;
|
2015-01-21 11:55:20 +00:00
|
|
|
|
},
|
|
|
|
|
getJidFromSSRC: function (ssrc) {
|
2015-07-14 13:35:13 +00:00
|
|
|
|
if (!this.isConferenceInProgress())
|
2015-01-21 11:55:20 +00:00
|
|
|
|
return null;
|
2015-07-14 13:35:13 +00:00
|
|
|
|
return connection.jingle.activecall.getSsrcOwner(ssrc);
|
2015-02-09 10:21:23 +00:00
|
|
|
|
},
|
2015-07-22 20:30:42 +00:00
|
|
|
|
// Returns true iff we have joined the MUC.
|
|
|
|
|
isMUCJoined: function () {
|
2015-09-29 16:55:39 +00:00
|
|
|
|
return connection === null ? false : connection.emuc.joined;
|
2015-02-09 10:21:23 +00:00
|
|
|
|
},
|
|
|
|
|
getSessions: function () {
|
|
|
|
|
return connection.jingle.sessions;
|
2015-03-23 16:12:24 +00:00
|
|
|
|
},
|
|
|
|
|
removeStream: function (stream) {
|
2015-07-09 13:04:08 +00:00
|
|
|
|
if (!this.isConferenceInProgress())
|
2015-03-23 16:12:24 +00:00
|
|
|
|
return;
|
|
|
|
|
connection.jingle.activecall.peerconnection.removeStream(stream);
|
2015-09-02 09:56:22 +00:00
|
|
|
|
},
|
|
|
|
|
filter_special_chars: function (text) {
|
|
|
|
|
return SDPUtil.filter_special_chars(text);
|
2015-01-19 09:20:00 +00:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2015-01-21 15:13:13 +00:00
|
|
|
|
module.exports = XMPP;
|