Fixes join and leave methods. Adds communication with jicofo. Implements custom commands methods.
This commit is contained in:
parent
455a6e10fe
commit
1bba8d2032
|
@ -1,5 +1,3 @@
|
|||
var room = null;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a JitsiConference object with the given name and properties.
|
||||
|
@ -15,13 +13,16 @@ function JitsiConference(options) {
|
|||
this.options = options;
|
||||
this.connection = this.options.connection;
|
||||
this.xmpp = this.connection.xmpp;
|
||||
this.room = this.xmpp.createRoom(this.options.name, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Joins the conference.
|
||||
* @param password {string} the password
|
||||
*/
|
||||
JitsiConference.prototype.join = function () {
|
||||
room = this.xmpp.joinRoom(this.options.name, null, null);
|
||||
JitsiConference.prototype.join = function (password) {
|
||||
|
||||
this.room.joinRoom(password);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -29,7 +30,7 @@ JitsiConference.prototype.join = function () {
|
|||
*/
|
||||
JitsiConference.prototype.leave = function () {
|
||||
this.xmpp.leaveRoom(room.roomjid);
|
||||
room = null;
|
||||
this.room = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -60,7 +61,7 @@ JitsiConference.prototype.getLocalTracks = function () {
|
|||
* Note: consider adding eventing functionality by extending an EventEmitter impl, instead of rolling ourselves
|
||||
*/
|
||||
JitsiConference.prototype.on = function (eventId, handler) {
|
||||
this.xmpp.addListener(eventId, handler);
|
||||
this.add.addListener(eventId, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -71,7 +72,7 @@ JitsiConference.prototype.on = function (eventId, handler) {
|
|||
* Note: consider adding eventing functionality by extending an EventEmitter impl, instead of rolling ourselves
|
||||
*/
|
||||
JitsiConference.prototype.off = function (eventId, handler) {
|
||||
this.xmpp.removeListener(event, listener);
|
||||
this.room.removeListener(eventId, listener);
|
||||
}
|
||||
|
||||
// Common aliases for event emitter
|
||||
|
@ -84,7 +85,7 @@ JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off
|
|||
* @param handler {Function} handler for the command
|
||||
*/
|
||||
JitsiConference.prototype.addCommandListener = function (command, handler) {
|
||||
|
||||
this.room.addPresenceListener(command, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -92,7 +93,7 @@ JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off
|
|||
* @param command {String} the name of the command
|
||||
*/
|
||||
JitsiConference.prototype.removeCommandListener = function (command) {
|
||||
|
||||
this.room.removePresenceListener(command);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,7 +101,27 @@ JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off
|
|||
* @param message the text message.
|
||||
*/
|
||||
JitsiConference.prototype.sendTextMessage = function (message) {
|
||||
room.send
|
||||
this.room.sendMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send presence command.
|
||||
* @param name the name of the command.
|
||||
* @param values Object with keys and values that will be send.
|
||||
**/
|
||||
JitsiConference.prototype.sendCommand = function (name, values) {
|
||||
this.room.addToPresence(name, values);
|
||||
this.room.sendPresence();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send presence command one time.
|
||||
* @param name the name of the command.
|
||||
* @param values Object with keys and values that will be send.
|
||||
**/
|
||||
JitsiConference.prototype.sendCommandOnce = function (name, values) {
|
||||
this.sendCommand(name, values);
|
||||
this.removeCommand(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -108,13 +129,9 @@ JitsiConference.prototype.sendTextMessage = function (message) {
|
|||
* @param name the name of the command.
|
||||
* @param values Object with keys and values that will be send.
|
||||
* @param persistent if false the command will be sent only one time
|
||||
* @param successCallback will be called when the command is successfully send.
|
||||
* @param errorCallback will be called when the command is not sent successfully.
|
||||
* @returns {Promise.<{void}, JitsiConferenceError>} A promise that returns an array of created streams if resolved,
|
||||
* or an JitsiConferenceError if rejected.
|
||||
*/
|
||||
JitsiConference.prototype.sendCommand = function (name, values, persistent) {
|
||||
|
||||
**/
|
||||
JitsiConference.prototype.removeCommand = function (name) {
|
||||
this.room.removeFromPresence(name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +139,7 @@ JitsiConference.prototype.sendCommand = function (name, values, persistent) {
|
|||
* @param name the display name to set
|
||||
*/
|
||||
JitsiConference.prototype.setDisplayName = function(name) {
|
||||
room.addToPresence("nick", {attributes: {xmlns: 'http://jabber.org/protocol/nick'}, value: name});
|
||||
this.room.addToPresence("nick", {attributes: {xmlns: 'http://jabber.org/protocol/nick'}, value: name});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,5 +158,14 @@ JitsiConference.prototype.getParticipants = function() {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {JitsiParticipant} the participant in this conference with the specified id (or
|
||||
* null if there isn't one).
|
||||
* @param id the id of the participant.
|
||||
*/
|
||||
JitsiConference.prototype.getParticipantById = function(id) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
module.exports = JitsiConference;
|
||||
|
|
|
@ -62,7 +62,15 @@ var JitsiConferenceEvents = {
|
|||
/**
|
||||
* Indicates that the connection to the conference has been restored.
|
||||
*/
|
||||
CONNECTION_ESTABLISHED: "conference.connecionEstablished"
|
||||
CONNECTION_RESTORED: "conference.connecionRestored",
|
||||
/**
|
||||
* Indicates that conference has been joined.
|
||||
*/
|
||||
CONFERENCE_JOINED: "conference.joined",
|
||||
/**
|
||||
* Indicates that conference has been left.
|
||||
*/
|
||||
CONFERENCE_LEFT: "conference.left"
|
||||
};
|
||||
|
||||
module.exports = JitsiConferenceEvents;
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
var JitsiConference = require("./JitsiConference");
|
||||
var XMPP = require("./modules/xmpp/xmpp");
|
||||
|
||||
function wrapper()
|
||||
{
|
||||
var jitsiconnectioninstance = new JitsiConnection();
|
||||
this.a = jitsiconnectioninstance.a();
|
||||
}
|
||||
/**
|
||||
* Creates new connection object for the Jitsi Meet server side video conferencing service. Provides access to the
|
||||
* JitsiConference interface.
|
||||
|
@ -20,6 +15,7 @@ function JitsiConnection(appID, token, options) {
|
|||
this.token = token;
|
||||
this.options = options;
|
||||
this.xmpp = new XMPP(options);
|
||||
this.conferences = {};
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,7 +50,8 @@ JitsiConnection.prototype.setToken = function (token) {
|
|||
* @returns {JitsiConference} returns the new conference object.
|
||||
*/
|
||||
JitsiConnection.prototype.initJitsiConference = function (name, options) {
|
||||
return new JitsiConference({name: name, config: options, connection: this});
|
||||
this.conferences[name] = new JitsiConference({name: name, config: options, connection: this});
|
||||
return this.conferences[name];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
/**
|
||||
* Represents a participant in (a member of) a conference.
|
||||
*/
|
||||
function JitsiParticipant(){
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {JitsiConference} The conference that this participant belongs to.
|
||||
*/
|
||||
JitsiParticipant.prototype.getConference = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Array.<JitsiTrack>} The list of media tracks for this participant.
|
||||
*/
|
||||
JitsiParticipant.prototype.getTracks = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {String} The ID (i.e. JID) of this participant.
|
||||
*/
|
||||
JitsiParticipant.prototype.getId = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {String} The human-readable display name of this participant.
|
||||
*/
|
||||
JitsiParticipant.prototype.getDisplayName = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Boolean} Whether this participant is a moderator or not.
|
||||
*/
|
||||
JitsiParticipant.prototype.isModerator = function() {
|
||||
|
||||
}
|
||||
|
||||
// Gets a link to an etherpad instance advertised by the participant?
|
||||
//JitsiParticipant.prototype.getEtherpad = function() {
|
||||
//
|
||||
//}
|
||||
|
||||
|
||||
/*
|
||||
* @returns {Boolean} Whether this participant has muted their audio.
|
||||
*/
|
||||
JitsiParticipant.prototype.isAudioMuted = function() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @returns {Boolean} Whether this participant has muted their video.
|
||||
*/
|
||||
JitsiParticipant.prototype.isVideoMuted = function() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @returns {???} The latest statistics reported by this participant (i.e. info used to populate the GSM bars)
|
||||
* TODO: do we expose this or handle it internally?
|
||||
*/
|
||||
JitsiParticipant.prototype.getLatestStats = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {String} The role of this participant.
|
||||
*/
|
||||
JitsiParticipant.prototype.getRole = function() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @returns {Boolean} Whether this participant is the conference focus (i.e. jicofo).
|
||||
*/
|
||||
JitsiParticipant.prototype.isFocus = function() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @returns {Boolean} Whether this participant is a conference recorder (i.e. jirecon).
|
||||
*/
|
||||
JitsiParticipant.prototype.isRecorder = function() {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* @returns {Boolean} Whether this participant is a SIP gateway (i.e. jigasi).
|
||||
*/
|
||||
JitsiParticipant.prototype.isSipGateway = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {String} The ID for this participant's avatar.
|
||||
*/
|
||||
JitsiParticipant.prototype.getAvatarId = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {Boolean} Whether this participant is currently sharing their screen.
|
||||
*/
|
||||
JitsiParticipant.prototype.isScreenSharing = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {String} The user agent of this participant (i.e. browser userAgent string).
|
||||
*/
|
||||
JitsiParticipant.prototype.getUserAgent = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks the participant from the conference (requires certain privileges).
|
||||
*/
|
||||
JitsiParticipant.prototype.kick = function() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks this participant to mute themselves.
|
||||
*/
|
||||
JitsiParticipant.prototype.askToMute = function() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
module.exports = JitsiParticipant();
|
|
@ -26,7 +26,7 @@ JitsiTrack.prototype.getType = function() {
|
|||
};
|
||||
|
||||
/**
|
||||
* Returns the JitsiParticipant to which this track belongs, or null if it is a local track.
|
||||
* @returns {JitsiParticipant} to which this track belongs, or null if it is a local track.
|
||||
*/
|
||||
JitsiTrack.prototype.getParitcipant() = function() {
|
||||
|
||||
|
|
7124
lib-jitsi-meet.js
7124
lib-jitsi-meet.js
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -21,17 +21,17 @@ function Settings(conferenceID) {
|
|||
this.userId;
|
||||
this.language = null;
|
||||
this.confSettings = null;
|
||||
this.conferenceID = conferenceID;
|
||||
if (supportsLocalStorage()) {
|
||||
if(!window.localStorage.jitsiConferences)
|
||||
window.localStorage.jitsiConferences = {}
|
||||
if (!window.localStorage.jitsiConferences[conferenceID]) {
|
||||
window.localStorage.jitsiConferences[conferenceID] = {}
|
||||
}
|
||||
this.confSettings = window.localStorage.jitsiConferences[conferenceID];
|
||||
if(!window.localStorage.getItem(conferenceID))
|
||||
this.confSettings = {};
|
||||
else
|
||||
this.confSettings = JSON.parse(window.localStorage.getItem(conferenceID));
|
||||
if(!this.confSettings.jitsiMeetId) {
|
||||
this.confSettings.jitsiMeetId = generateUniqueId();
|
||||
console.log("generated id",
|
||||
this.confSettings.jitsiMeetId);
|
||||
this.save();
|
||||
}
|
||||
this.userId = this.confSettings.jitsiMeetId || '';
|
||||
this.email = this.confSettings.email || '';
|
||||
|
@ -43,16 +43,23 @@ function Settings(conferenceID) {
|
|||
}
|
||||
}
|
||||
|
||||
Settings.prototype.save = function () {
|
||||
if(!supportsLocalStorage())
|
||||
window.localStorage.setItem(this.conferenceID, JSON.stringify(this.confSettings));
|
||||
}
|
||||
|
||||
Settings.prototype.setDisplayName = function (newDisplayName) {
|
||||
this.displayName = newDisplayName;
|
||||
if(this.confSettings != null)
|
||||
this.confSettings.displayname = displayName;
|
||||
this.save();
|
||||
return this.displayName;
|
||||
},
|
||||
Settings.prototype.setEmail = function (newEmail) {
|
||||
this.email = newEmail;
|
||||
if(this.confSettings != null)
|
||||
this.confSettings.email = newEmail;
|
||||
this.save();
|
||||
return this.email;
|
||||
},
|
||||
Settings.prototype.getSettings = function () {
|
||||
|
@ -67,6 +74,7 @@ Settings.prototype.setLanguage = function (lang) {
|
|||
this.language = lang;
|
||||
if(this.confSettings != null)
|
||||
this.confSettings.language = lang;
|
||||
this.save();
|
||||
}
|
||||
|
||||
module.exports = Settings;
|
||||
|
|
|
@ -9,6 +9,7 @@ var transform = require("sdp-transform");
|
|||
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
|
||||
var RTCBrowserType = require("../RTC/RTCBrowserType");
|
||||
var SSRCReplacement = require("./LocalSSRCReplacement");
|
||||
var RTC = require("../RTC/RTC");
|
||||
|
||||
// Jingle stuff
|
||||
function JingleSessionPC(me, sid, connection, service, eventEmitter) {
|
||||
|
@ -86,7 +87,7 @@ JingleSessionPC.prototype.doInitialize = function () {
|
|||
|
||||
this.peerconnection = new TraceablePeerConnection(
|
||||
this.connection.jingle.ice_config,
|
||||
APP.RTC.getPCConstraints(),
|
||||
RTC.getPCConstraints(),
|
||||
this);
|
||||
|
||||
this.peerconnection.onicecandidate = function (event) {
|
||||
|
@ -147,15 +148,20 @@ JingleSessionPC.prototype.doInitialize = function () {
|
|||
this.peerconnection.onnegotiationneeded = function (event) {
|
||||
self.eventEmitter.emit(XMPPEvents.PEERCONNECTION_READY, self);
|
||||
};
|
||||
// add any local and relayed stream
|
||||
APP.RTC.localStreams.forEach(function(stream) {
|
||||
self.peerconnection.addStream(stream.getOriginalStream());
|
||||
});
|
||||
|
||||
this.relayedStreams.forEach(function(stream) {
|
||||
self.peerconnection.addStream(stream);
|
||||
});
|
||||
};
|
||||
|
||||
JingleSessionPC.prototype.addLocalStreams = function (localStreams) {
|
||||
var self = this;
|
||||
// add any local and relayed stream
|
||||
localStreams.forEach(function(stream) {
|
||||
self.peerconnection.addStream(stream.getOriginalStream());
|
||||
});
|
||||
}
|
||||
|
||||
function onIceConnectionStateChange(sid, session) {
|
||||
switch (session.peerconnection.iceConnectionState) {
|
||||
case 'checking':
|
||||
|
@ -1307,8 +1313,6 @@ JingleSessionPC.onJingleError = function (session, error)
|
|||
|
||||
JingleSessionPC.onJingleFatalError = function (session, error)
|
||||
{
|
||||
this.service.sessionTerminated = true;
|
||||
this.connection.emuc.doLeave();
|
||||
this.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);
|
||||
this.eventEmitter.emit(XMPPEvents.JINGLE_FATAL_ERROR, session, error);
|
||||
}
|
||||
|
@ -1391,7 +1395,7 @@ function sendKeyframe(pc) {
|
|||
JingleSessionPC.prototype.remoteStreamAdded = function (data, times) {
|
||||
var self = this;
|
||||
var thessrc;
|
||||
var streamId = APP.RTC.getStreamID(data.stream);
|
||||
var streamId = RTC.getStreamID(data.stream);
|
||||
|
||||
// look up an associated JID for a stream id
|
||||
if (!streamId) {
|
||||
|
@ -1426,14 +1430,14 @@ JingleSessionPC.prototype.remoteStreamAdded = function (data, times) {
|
|||
}
|
||||
}
|
||||
|
||||
APP.RTC.createRemoteStream(data, this.sid, thessrc);
|
||||
RTC.createRemoteStream(data, this.sid, thessrc);
|
||||
|
||||
var isVideo = data.stream.getVideoTracks().length > 0;
|
||||
// an attempt to work around https://github.com/jitsi/jitmeet/issues/32
|
||||
if (isVideo &&
|
||||
data.peerjid && this.peerjid === data.peerjid &&
|
||||
data.stream.getVideoTracks().length === 0 &&
|
||||
APP.RTC.localVideo.getTracks().length > 0) {
|
||||
RTC.localVideo.getTracks().length > 0) {
|
||||
window.setTimeout(function () {
|
||||
sendKeyframe(self.peerconnection);
|
||||
}, 3000);
|
||||
|
|
|
@ -6,13 +6,6 @@ var Settings = require("../settings/Settings");
|
|||
var AuthenticationEvents
|
||||
= require("../../service/authentication/AuthenticationEvents");
|
||||
|
||||
/**
|
||||
* Contains logic responsible for enabling/disabling functionality available
|
||||
* only to moderator users.
|
||||
*/
|
||||
var connection = null;
|
||||
var focusUserJid;
|
||||
|
||||
function createExpBackoffTimer(step) {
|
||||
var count = 1;
|
||||
return function (reset) {
|
||||
|
@ -28,402 +21,396 @@ function createExpBackoffTimer(step) {
|
|||
};
|
||||
}
|
||||
|
||||
var getNextTimeout = createExpBackoffTimer(1000);
|
||||
var getNextErrorTimeout = createExpBackoffTimer(1000);
|
||||
|
||||
|
||||
|
||||
|
||||
function Moderator(roomName, xmpp, emitter) {
|
||||
this.roomName = roomName;
|
||||
this.xmppService = xmpp;
|
||||
this.getNextTimeout = createExpBackoffTimer(1000);
|
||||
this.getNextErrorTimeout = createExpBackoffTimer(1000);
|
||||
// External authentication stuff
|
||||
var externalAuthEnabled = false;
|
||||
this.externalAuthEnabled = false;
|
||||
this.settings = new Settings(roomName);
|
||||
// Sip gateway can be enabled by configuring Jigasi host in config.js or
|
||||
// it will be enabled automatically if focus detects the component through
|
||||
// service discovery.
|
||||
var sipGatewayEnabled = null;
|
||||
this.sipGatewayEnabled = this.xmppService.options.hosts.call_control !== undefined;
|
||||
|
||||
var eventEmitter = null;
|
||||
this.eventEmitter = emitter;
|
||||
|
||||
var Moderator = {
|
||||
isModerator: function () {
|
||||
return connection && connection.emuc.isModerator();
|
||||
},
|
||||
|
||||
isPeerModerator: function (peerJid) {
|
||||
return connection &&
|
||||
connection.emuc.getMemberRole(peerJid) === 'moderator';
|
||||
},
|
||||
|
||||
isExternalAuthEnabled: function () {
|
||||
return externalAuthEnabled;
|
||||
},
|
||||
|
||||
isSipGatewayEnabled: function () {
|
||||
return sipGatewayEnabled;
|
||||
},
|
||||
|
||||
setConnection: function (con) {
|
||||
connection = con;
|
||||
},
|
||||
|
||||
init: function (xmpp, emitter) {
|
||||
this.xmppService = xmpp;
|
||||
sipGatewayEnabled = this.xmppService.options.hosts.call_control !== undefined;
|
||||
eventEmitter = emitter;
|
||||
|
||||
// Message listener that talks to POPUP window
|
||||
function listener(event) {
|
||||
if (event.data && event.data.sessionId) {
|
||||
if (event.origin !== window.location.origin) {
|
||||
console.warn("Ignoring sessionId from different origin: " +
|
||||
event.origin);
|
||||
return;
|
||||
}
|
||||
localStorage.setItem('sessionId', event.data.sessionId);
|
||||
// After popup is closed we will authenticate
|
||||
this.connection = this.xmppService.connection;
|
||||
this.focusUserJid;
|
||||
//FIXME:
|
||||
// Message listener that talks to POPUP window
|
||||
function listener(event) {
|
||||
if (event.data && event.data.sessionId) {
|
||||
if (event.origin !== window.location.origin) {
|
||||
console.warn("Ignoring sessionId from different origin: " +
|
||||
event.origin);
|
||||
return;
|
||||
}
|
||||
localStorage.setItem('sessionId', event.data.sessionId);
|
||||
// After popup is closed we will authenticate
|
||||
}
|
||||
// Register
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("message", listener, false);
|
||||
} else {
|
||||
window.attachEvent("onmessage", listener);
|
||||
}
|
||||
},
|
||||
}
|
||||
// Register
|
||||
if (window.addEventListener) {
|
||||
window.addEventListener("message", listener, false);
|
||||
} else {
|
||||
window.attachEvent("onmessage", listener);
|
||||
}
|
||||
}
|
||||
|
||||
onMucMemberLeft: function (jid) {
|
||||
console.info("Someone left is it focus ? " + jid);
|
||||
var resource = Strophe.getResourceFromJid(jid);
|
||||
if (resource === 'focus' && !this.xmppService.sessionTerminated) {
|
||||
console.info(
|
||||
"Focus has left the room - leaving conference");
|
||||
//hangUp();
|
||||
// We'd rather reload to have everything re-initialized
|
||||
// FIXME: show some message before reload
|
||||
location.reload();
|
||||
}
|
||||
},
|
||||
|
||||
setFocusUserJid: function (focusJid) {
|
||||
if (!focusUserJid) {
|
||||
focusUserJid = focusJid;
|
||||
console.info("Focus jid set to: " + focusUserJid);
|
||||
}
|
||||
},
|
||||
Moderator.prototype.isExternalAuthEnabled = function () {
|
||||
return this.externalAuthEnabled;
|
||||
};
|
||||
|
||||
getFocusUserJid: function () {
|
||||
return focusUserJid;
|
||||
},
|
||||
Moderator.prototype.isSipGatewayEnabled = function () {
|
||||
return this.sipGatewayEnabled;
|
||||
};
|
||||
|
||||
getFocusComponent: function () {
|
||||
// Get focus component address
|
||||
var focusComponent = this.xmppService.options.hosts.focus;
|
||||
// If not specified use default: 'focus.domain'
|
||||
if (!focusComponent) {
|
||||
focusComponent = 'focus.' + this.xmppService.options.hosts.domain;
|
||||
}
|
||||
return focusComponent;
|
||||
},
|
||||
|
||||
createConferenceIq: function (roomName) {
|
||||
// Generate create conference IQ
|
||||
var elem = $iq({to: Moderator.getFocusComponent(), type: 'set'});
|
||||
|
||||
// Session Id used for authentication
|
||||
var sessionId = localStorage.getItem('sessionId');
|
||||
var machineUID = Settings.getSettings().uid;
|
||||
|
||||
Moderator.prototype.onMucMemberLeft = function (jid) {
|
||||
console.info("Someone left is it focus ? " + jid);
|
||||
var resource = Strophe.getResourceFromJid(jid);
|
||||
if (resource === 'focus' && !this.xmppService.sessionTerminated) {
|
||||
console.info(
|
||||
"Focus has left the room - leaving conference");
|
||||
//hangUp();
|
||||
// We'd rather reload to have everything re-initialized
|
||||
//FIXME: show some message before reload
|
||||
this.eventEmitter.emit(XMPPEvents.FOCUS_LEFT);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Moderator.prototype.setFocusUserJid = function (focusJid) {
|
||||
if (!this.focusUserJid) {
|
||||
this.focusUserJid = focusJid;
|
||||
console.info("Focus jid set to: " + this.focusUserJid);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Moderator.prototype.getFocusUserJid = function () {
|
||||
return this.focusUserJid;
|
||||
};
|
||||
|
||||
Moderator.prototype.getFocusComponent = function () {
|
||||
// Get focus component address
|
||||
var focusComponent = this.xmppService.options.hosts.focus;
|
||||
// If not specified use default: 'focus.domain'
|
||||
if (!focusComponent) {
|
||||
focusComponent = 'focus.' + this.xmppService.options.hosts.domain;
|
||||
}
|
||||
return focusComponent;
|
||||
};
|
||||
|
||||
Moderator.prototype.createConferenceIq = function () {
|
||||
// Generate create conference IQ
|
||||
var elem = $iq({to: this.getFocusComponent(), type: 'set'});
|
||||
|
||||
// Session Id used for authentication
|
||||
var sessionId = localStorage.getItem('sessionId');
|
||||
var machineUID = this.settings.getSettings().uid;
|
||||
|
||||
console.info(
|
||||
"Session ID: " + sessionId + " machine UID: " + machineUID);
|
||||
|
||||
elem.c('conference', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
room: roomName,
|
||||
'machine-uid': machineUID
|
||||
});
|
||||
elem.c('conference', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
room: this.roomName,
|
||||
'machine-uid': machineUID
|
||||
});
|
||||
|
||||
if (sessionId) {
|
||||
elem.attrs({ 'session-id': sessionId});
|
||||
}
|
||||
|
||||
if (this.xmppService.options.hosts.bridge !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{ name: 'bridge', value: this.xmppService.options.hosts.bridge})
|
||||
.up();
|
||||
}
|
||||
// Tell the focus we have Jigasi configured
|
||||
if (this.xmppService.options.hosts.call_control !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{ name: 'call_control', value: this.xmppService.options.hosts.call_control})
|
||||
.up();
|
||||
}
|
||||
if (this.xmppService.options.channelLastN !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{ name: 'channelLastN', value: this.xmppService.options.channelLastN})
|
||||
.up();
|
||||
}
|
||||
if (this.xmppService.options.adaptiveLastN !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{ name: 'adaptiveLastN', value: this.xmppService.options.adaptiveLastN})
|
||||
.up();
|
||||
}
|
||||
if (this.xmppService.options.adaptiveSimulcast !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{ name: 'adaptiveSimulcast', value: this.xmppService.options.adaptiveSimulcast})
|
||||
.up();
|
||||
}
|
||||
if (this.xmppService.options.openSctp !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{ name: 'openSctp', value: this.xmppService.options.openSctp})
|
||||
.up();
|
||||
}
|
||||
if(this.xmppService.options.startAudioMuted !== undefined)
|
||||
{
|
||||
elem.c(
|
||||
'property',
|
||||
{ name: 'startAudioMuted', value: this.xmppService.options.startAudioMuted})
|
||||
.up();
|
||||
}
|
||||
if(this.xmppService.options.startVideoMuted !== undefined)
|
||||
{
|
||||
elem.c(
|
||||
'property',
|
||||
{ name: 'startVideoMuted', value: this.xmppService.options.startVideoMuted})
|
||||
.up();
|
||||
}
|
||||
if (sessionId) {
|
||||
elem.attrs({ 'session-id': sessionId});
|
||||
}
|
||||
if (this.xmppService.options.hosts.bridge !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{ name: 'simulcastMode', value: 'rewriting'})
|
||||
{name: 'bridge',value: this.xmppService.options.hosts.bridge})
|
||||
.up();
|
||||
elem.up();
|
||||
return elem;
|
||||
},
|
||||
}
|
||||
// Tell the focus we have Jigasi configured
|
||||
if (this.xmppService.options.hosts.call_control !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{name: 'call_control',value: this.xmppService.options.hosts.call_control})
|
||||
.up();
|
||||
}
|
||||
if (this.xmppService.options.channelLastN !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{name: 'channelLastN',value: this.xmppService.options.channelLastN})
|
||||
.up();
|
||||
}
|
||||
if (this.xmppService.options.adaptiveLastN !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{name: 'adaptiveLastN',value: this.xmppService.options.adaptiveLastN})
|
||||
.up();
|
||||
}
|
||||
if (this.xmppService.options.adaptiveSimulcast !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{name: 'adaptiveSimulcast',value: this.xmppService.options.adaptiveSimulcast})
|
||||
.up();
|
||||
}
|
||||
if (this.xmppService.options.openSctp !== undefined) {
|
||||
elem.c(
|
||||
'property',
|
||||
{name: 'openSctp',value: this.xmppService.options.openSctp})
|
||||
.up();
|
||||
}
|
||||
if(this.xmppService.options.startAudioMuted !== undefined)
|
||||
{
|
||||
elem.c(
|
||||
'property',
|
||||
{name: 'startAudioMuted',value: this.xmppService.options.startAudioMuted})
|
||||
.up();
|
||||
}
|
||||
if(this.xmppService.options.startVideoMuted !== undefined)
|
||||
{
|
||||
elem.c(
|
||||
'property',
|
||||
{name: 'startVideoMuted',value: this.xmppService.options.startVideoMuted})
|
||||
.up();
|
||||
}
|
||||
elem.c(
|
||||
'property',
|
||||
{name: 'simulcastMode',value: 'rewriting'})
|
||||
.up();
|
||||
elem.up();
|
||||
return elem;
|
||||
};
|
||||
|
||||
parseSessionId: function (resultIq) {
|
||||
var sessionId = $(resultIq).find('conference').attr('session-id');
|
||||
if (sessionId) {
|
||||
console.info('Received sessionId: ' + sessionId);
|
||||
localStorage.setItem('sessionId', sessionId);
|
||||
}
|
||||
},
|
||||
|
||||
parseConfigOptions: function (resultIq) {
|
||||
Moderator.prototype.parseSessionId = function (resultIq) {
|
||||
var sessionId = $(resultIq).find('conference').attr('session-id');
|
||||
if (sessionId) {
|
||||
console.info('Received sessionId: ' + sessionId);
|
||||
localStorage.setItem('sessionId', sessionId);
|
||||
}
|
||||
};
|
||||
|
||||
Moderator.setFocusUserJid(
|
||||
$(resultIq).find('conference').attr('focusjid'));
|
||||
Moderator.prototype.parseConfigOptions = function (resultIq) {
|
||||
|
||||
var authenticationEnabled
|
||||
= $(resultIq).find(
|
||||
'>conference>property' +
|
||||
'[name=\'authentication\'][value=\'true\']').length > 0;
|
||||
this.setFocusUserJid(
|
||||
$(resultIq).find('conference').attr('focusjid'));
|
||||
|
||||
console.info("Authentication enabled: " + authenticationEnabled);
|
||||
|
||||
externalAuthEnabled = $(resultIq).find(
|
||||
'>conference>property' +
|
||||
'[name=\'externalAuth\'][value=\'true\']').length > 0;
|
||||
|
||||
console.info('External authentication enabled: ' + externalAuthEnabled);
|
||||
|
||||
if (!externalAuthEnabled) {
|
||||
// We expect to receive sessionId in 'internal' authentication mode
|
||||
Moderator.parseSessionId(resultIq);
|
||||
}
|
||||
|
||||
var authIdentity = $(resultIq).find('>conference').attr('identity');
|
||||
|
||||
eventEmitter.emit(AuthenticationEvents.IDENTITY_UPDATED,
|
||||
authenticationEnabled, authIdentity);
|
||||
|
||||
// Check if focus has auto-detected Jigasi component(this will be also
|
||||
// included if we have passed our host from the config)
|
||||
if ($(resultIq).find(
|
||||
var authenticationEnabled
|
||||
= $(resultIq).find(
|
||||
'>conference>property' +
|
||||
'[name=\'sipGatewayEnabled\'][value=\'true\']').length) {
|
||||
sipGatewayEnabled = true;
|
||||
}
|
||||
|
||||
console.info("Sip gateway enabled: " + sipGatewayEnabled);
|
||||
},
|
||||
'[name=\'authentication\'][value=\'true\']').length > 0;
|
||||
|
||||
// FIXME: we need to show the fact that we're waiting for the focus
|
||||
// to the user(or that focus is not available)
|
||||
allocateConferenceFocus: function (roomName, callback) {
|
||||
// Try to use focus user JID from the config
|
||||
Moderator.setFocusUserJid(this.xmppService.options.focusUserJid);
|
||||
// Send create conference IQ
|
||||
var iq = Moderator.createConferenceIq(roomName);
|
||||
var self = this;
|
||||
connection.sendIQ(
|
||||
iq,
|
||||
function (result) {
|
||||
console.info("Authentication enabled: " + authenticationEnabled);
|
||||
|
||||
// Setup config options
|
||||
Moderator.parseConfigOptions(result);
|
||||
this.externalAuthEnabled = $(resultIq).find(
|
||||
'>conference>property' +
|
||||
'[name=\'externalAuth\'][value=\'true\']').length > 0;
|
||||
|
||||
if ('true' === $(result).find('conference').attr('ready')) {
|
||||
// Reset both timers
|
||||
getNextTimeout(true);
|
||||
getNextErrorTimeout(true);
|
||||
// Exec callback
|
||||
callback();
|
||||
} else {
|
||||
var waitMs = getNextTimeout();
|
||||
console.info("Waiting for the focus... " + waitMs);
|
||||
// Reset error timeout
|
||||
getNextErrorTimeout(true);
|
||||
window.setTimeout(
|
||||
function () {
|
||||
Moderator.allocateConferenceFocus(
|
||||
roomName, callback);
|
||||
}, waitMs);
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
// Invalid session ? remove and try again
|
||||
// without session ID to get a new one
|
||||
var invalidSession
|
||||
= $(error).find('>error>session-invalid').length;
|
||||
if (invalidSession) {
|
||||
console.info("Session expired! - removing");
|
||||
localStorage.removeItem("sessionId");
|
||||
}
|
||||
if ($(error).find('>error>graceful-shutdown').length) {
|
||||
eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);
|
||||
return;
|
||||
}
|
||||
// Check for error returned by the reservation system
|
||||
var reservationErr = $(error).find('>error>reservation-error');
|
||||
if (reservationErr.length) {
|
||||
// Trigger error event
|
||||
var errorCode = reservationErr.attr('error-code');
|
||||
var errorMsg;
|
||||
if ($(error).find('>error>text')) {
|
||||
errorMsg = $(error).find('>error>text').text();
|
||||
}
|
||||
eventEmitter.emit(
|
||||
XMPPEvents.RESERVATION_ERROR, errorCode, errorMsg);
|
||||
return;
|
||||
}
|
||||
// Not authorized to create new room
|
||||
if ($(error).find('>error>not-authorized').length) {
|
||||
console.warn("Unauthorized to start the conference", error);
|
||||
var toDomain
|
||||
= Strophe.getDomainFromJid(error.getAttribute('to'));
|
||||
if (toDomain !== this.xmppService.options.hosts.anonymousdomain) {
|
||||
// FIXME: "is external" should come either from
|
||||
// the focus or config.js
|
||||
externalAuthEnabled = true;
|
||||
}
|
||||
eventEmitter.emit(
|
||||
XMPPEvents.AUTHENTICATION_REQUIRED,
|
||||
function () {
|
||||
Moderator.allocateConferenceFocus(
|
||||
roomName, callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var waitMs = getNextErrorTimeout();
|
||||
console.error("Focus error, retry after " + waitMs, error);
|
||||
// Show message
|
||||
var focusComponent = Moderator.getFocusComponent();
|
||||
var retrySec = waitMs / 1000;
|
||||
// FIXME: message is duplicated ?
|
||||
// Do not show in case of session invalid
|
||||
// which means just a retry
|
||||
if (!invalidSession) {
|
||||
eventEmitter.emit(XMPPEvents.FOCUS_DISCONNECTED,
|
||||
focusComponent, retrySec);
|
||||
}
|
||||
// Reset response timeout
|
||||
getNextTimeout(true);
|
||||
console.info('External authentication enabled: ' + this.externalAuthEnabled);
|
||||
|
||||
if (!this.externalAuthEnabled) {
|
||||
// We expect to receive sessionId in 'internal' authentication mode
|
||||
this.parseSessionId(resultIq);
|
||||
}
|
||||
|
||||
var authIdentity = $(resultIq).find('>conference').attr('identity');
|
||||
|
||||
this.eventEmitter.emit(AuthenticationEvents.IDENTITY_UPDATED,
|
||||
authenticationEnabled, authIdentity);
|
||||
|
||||
// Check if focus has auto-detected Jigasi component(this will be also
|
||||
// included if we have passed our host from the config)
|
||||
if ($(resultIq).find(
|
||||
'>conference>property' +
|
||||
'[name=\'sipGatewayEnabled\'][value=\'true\']').length) {
|
||||
this.sipGatewayEnabled = true;
|
||||
}
|
||||
|
||||
console.info("Sip gateway enabled: " + this.sipGatewayEnabled);
|
||||
};
|
||||
|
||||
// FIXME = we need to show the fact that we're waiting for the focus
|
||||
// to the user(or that focus is not available)
|
||||
Moderator.prototype.allocateConferenceFocus = function ( callback) {
|
||||
// Try to use focus user JID from the config
|
||||
this.setFocusUserJid(this.xmppService.options.focusUserJid);
|
||||
// Send create conference IQ
|
||||
var iq = this.createConferenceIq();
|
||||
var self = this;
|
||||
this.connection.sendIQ(
|
||||
iq,
|
||||
function (result) {
|
||||
|
||||
// Setup config options
|
||||
self.parseConfigOptions(result);
|
||||
|
||||
if ('true' === $(result).find('conference').attr('ready')) {
|
||||
// Reset both timers
|
||||
self.getNextTimeout(true);
|
||||
self.getNextErrorTimeout(true);
|
||||
// Exec callback
|
||||
callback();
|
||||
} else {
|
||||
var waitMs = self.getNextTimeout();
|
||||
console.info("Waiting for the focus... " + waitMs);
|
||||
// Reset error timeout
|
||||
self.getNextErrorTimeout(true);
|
||||
window.setTimeout(
|
||||
function () {
|
||||
Moderator.allocateConferenceFocus(roomName, callback);
|
||||
self.allocateConferenceFocus(callback);
|
||||
}, waitMs);
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
getLoginUrl: function (roomName, urlCallback) {
|
||||
var iq = $iq({to: Moderator.getFocusComponent(), type: 'get'});
|
||||
iq.c('login-url', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
room: roomName,
|
||||
'machine-uid': Settings.getSettings().uid
|
||||
});
|
||||
connection.sendIQ(
|
||||
iq,
|
||||
function (result) {
|
||||
var url = $(result).find('login-url').attr('url');
|
||||
url = url = decodeURIComponent(url);
|
||||
if (url) {
|
||||
console.info("Got auth url: " + url);
|
||||
urlCallback(url);
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to get auth url from the focus", result);
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
console.error("Get auth url error", error);
|
||||
},
|
||||
function (error) {
|
||||
// Invalid session ? remove and try again
|
||||
// without session ID to get a new one
|
||||
var invalidSession
|
||||
= $(error).find('>error>session-invalid').length;
|
||||
if (invalidSession) {
|
||||
console.info("Session expired! - removing");
|
||||
localStorage.removeItem("sessionId");
|
||||
}
|
||||
);
|
||||
},
|
||||
getPopupLoginUrl: function (roomName, urlCallback) {
|
||||
var iq = $iq({to: Moderator.getFocusComponent(), type: 'get'});
|
||||
iq.c('login-url', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
room: roomName,
|
||||
'machine-uid': Settings.getSettings().uid,
|
||||
popup: true
|
||||
});
|
||||
connection.sendIQ(
|
||||
iq,
|
||||
function (result) {
|
||||
var url = $(result).find('login-url').attr('url');
|
||||
url = url = decodeURIComponent(url);
|
||||
if (url) {
|
||||
console.info("Got POPUP auth url: " + url);
|
||||
urlCallback(url);
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to get POPUP auth url from the focus", result);
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
console.error('Get POPUP auth url error', error);
|
||||
if ($(error).find('>error>graceful-shutdown').length) {
|
||||
self.eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);
|
||||
return;
|
||||
}
|
||||
);
|
||||
},
|
||||
logout: function (callback) {
|
||||
var iq = $iq({to: Moderator.getFocusComponent(), type: 'set'});
|
||||
var sessionId = localStorage.getItem('sessionId');
|
||||
if (!sessionId) {
|
||||
callback();
|
||||
return;
|
||||
// Check for error returned by the reservation system
|
||||
var reservationErr = $(error).find('>error>reservation-error');
|
||||
if (reservationErr.length) {
|
||||
// Trigger error event
|
||||
var errorCode = reservationErr.attr('error-code');
|
||||
var errorMsg;
|
||||
if ($(error).find('>error>text')) {
|
||||
errorMsg = $(error).find('>error>text').text();
|
||||
}
|
||||
self.eventEmitter.emit(
|
||||
XMPPEvents.RESERVATION_ERROR, errorCode, errorMsg);
|
||||
return;
|
||||
}
|
||||
// Not authorized to create new room
|
||||
if ($(error).find('>error>not-authorized').length) {
|
||||
console.warn("Unauthorized to start the conference", error);
|
||||
var toDomain
|
||||
= Strophe.getDomainFromJid(error.getAttribute('to'));
|
||||
if (toDomain !== this.xmppService.options.hosts.anonymousdomain) {
|
||||
//FIXME: "is external" should come either from
|
||||
// the focus or config.js
|
||||
self.externalAuthEnabled = true;
|
||||
}
|
||||
self.eventEmitter.emit(
|
||||
XMPPEvents.AUTHENTICATION_REQUIRED,
|
||||
function () {
|
||||
self.allocateConferenceFocus(
|
||||
callback);
|
||||
});
|
||||
return;
|
||||
}
|
||||
var waitMs = self.getNextErrorTimeout();
|
||||
console.error("Focus error, retry after " + waitMs, error);
|
||||
// Show message
|
||||
var focusComponent = self.getFocusComponent();
|
||||
var retrySec = waitMs / 1000;
|
||||
//FIXME: message is duplicated ?
|
||||
// Do not show in case of session invalid
|
||||
// which means just a retry
|
||||
if (!invalidSession) {
|
||||
self.eventEmitter.emit(XMPPEvents.FOCUS_DISCONNECTED,
|
||||
focusComponent, retrySec);
|
||||
}
|
||||
// Reset response timeout
|
||||
self.getNextTimeout(true);
|
||||
window.setTimeout(
|
||||
function () {
|
||||
self.allocateConferenceFocus(callback);
|
||||
}, waitMs);
|
||||
}
|
||||
iq.c('logout', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
'session-id': sessionId
|
||||
});
|
||||
connection.sendIQ(
|
||||
iq,
|
||||
function (result) {
|
||||
var logoutUrl = $(result).find('logout').attr('logout-url');
|
||||
if (logoutUrl) {
|
||||
logoutUrl = decodeURIComponent(logoutUrl);
|
||||
}
|
||||
console.info("Log out OK, url: " + logoutUrl, result);
|
||||
localStorage.removeItem('sessionId');
|
||||
callback(logoutUrl);
|
||||
},
|
||||
function (error) {
|
||||
console.error("Logout error", error);
|
||||
);
|
||||
};
|
||||
|
||||
Moderator.prototype.getLoginUrl = function (urlCallback) {
|
||||
var iq = $iq({to: this.getFocusComponent(), type: 'get'});
|
||||
iq.c('login-url', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
room: this.roomName,
|
||||
'machine-uid': this.settings.getSettings().uid
|
||||
});
|
||||
this.connection.sendIQ(
|
||||
iq,
|
||||
function (result) {
|
||||
var url = $(result).find('login-url').attr('url');
|
||||
url = url = decodeURIComponent(url);
|
||||
if (url) {
|
||||
console.info("Got auth url: " + url);
|
||||
urlCallback(url);
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to get auth url from the focus", result);
|
||||
}
|
||||
);
|
||||
},
|
||||
function (error) {
|
||||
console.error("Get auth url error", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
Moderator.prototype.getPopupLoginUrl = function (urlCallback) {
|
||||
var iq = $iq({to: this.getFocusComponent(), type: 'get'});
|
||||
iq.c('login-url', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
room: this.roomName,
|
||||
'machine-uid': this.settings.getSettings().uid,
|
||||
popup: true
|
||||
});
|
||||
this.connection.sendIQ(
|
||||
iq,
|
||||
function (result) {
|
||||
var url = $(result).find('login-url').attr('url');
|
||||
url = url = decodeURIComponent(url);
|
||||
if (url) {
|
||||
console.info("Got POPUP auth url: " + url);
|
||||
urlCallback(url);
|
||||
} else {
|
||||
console.error(
|
||||
"Failed to get POPUP auth url from the focus", result);
|
||||
}
|
||||
},
|
||||
function (error) {
|
||||
console.error('Get POPUP auth url error', error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
Moderator.prototype.logout = function (callback) {
|
||||
var iq = $iq({to: this.getFocusComponent(), type: 'set'});
|
||||
var sessionId = localStorage.getItem('sessionId');
|
||||
if (!sessionId) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
iq.c('logout', {
|
||||
xmlns: 'http://jitsi.org/protocol/focus',
|
||||
'session-id': sessionId
|
||||
});
|
||||
this.connection.sendIQ(
|
||||
iq,
|
||||
function (result) {
|
||||
var logoutUrl = $(result).find('logout').attr('logout-url');
|
||||
if (logoutUrl) {
|
||||
logoutUrl = decodeURIComponent(logoutUrl);
|
||||
}
|
||||
console.info("Log out OK, url: " + logoutUrl, result);
|
||||
localStorage.removeItem('sessionId');
|
||||
callback(logoutUrl);
|
||||
},
|
||||
function (error) {
|
||||
console.error("Logout error", error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = Moderator;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
var XMPPEvents = require("../../service/xmpp/XMPPEvents");
|
||||
var Moderator = require("./moderator");
|
||||
var RTC = require("../RTC/RTC");
|
||||
var EventEmitter = require("events");
|
||||
|
||||
var parser = {
|
||||
packet2JSON: function (packet, nodes) {
|
||||
|
@ -46,6 +47,7 @@ var parser = {
|
|||
function ChatRoom(connection, jid, password, XMPP, eventEmitter)
|
||||
{
|
||||
this.eventEmitter = eventEmitter;
|
||||
this.roomEmitter = new EventEmitter();
|
||||
this.xmpp = XMPP;
|
||||
this.connection = connection;
|
||||
this.roomjid = Strophe.getBareJidFromJid(jid);
|
||||
|
@ -54,11 +56,24 @@ function ChatRoom(connection, jid, password, XMPP, eventEmitter)
|
|||
console.info("Joined MUC as " + this.myroomjid);
|
||||
this.members = {};
|
||||
this.presMap = {};
|
||||
this.presHandlers = {};
|
||||
this.joined = false;
|
||||
this.role = null;
|
||||
this.focusMucJid = null;
|
||||
this.bridgeIsDown = false;
|
||||
this.moderator = new Moderator(this.roomjid, this.xmpp, eventEmitter);
|
||||
this.initPresenceMap();
|
||||
this.readyToJoin = false;
|
||||
this.joinRequested = false;
|
||||
var self = this;
|
||||
this.moderator.allocateConferenceFocus(function()
|
||||
{
|
||||
self.readyToJoin = true;
|
||||
if(self.joinRequested)
|
||||
{
|
||||
self.join();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
ChatRoom.prototype.initPresenceMap = function () {
|
||||
|
@ -84,6 +99,18 @@ ChatRoom.prototype.initPresenceMap = function () {
|
|||
});
|
||||
};
|
||||
|
||||
ChatRoom.prototype.join = function (password) {
|
||||
if(password)
|
||||
this.password = password;
|
||||
if(!this.readyToJoin)
|
||||
{
|
||||
this.joinRequested = true;
|
||||
return;
|
||||
}
|
||||
this.joinRequested = false;
|
||||
this.sendPresence();
|
||||
}
|
||||
|
||||
ChatRoom.prototype.sendPresence = function () {
|
||||
if (!this.presMap['to']) {
|
||||
// Too early to send presence - not initialized
|
||||
|
@ -169,11 +196,11 @@ ChatRoom.prototype.onPresence = function (pres) {
|
|||
member.jid = tmp.attr('jid');
|
||||
member.isFocus = false;
|
||||
if (member.jid
|
||||
&& member.jid.indexOf(Moderator.getFocusUserJid() + "/") == 0) {
|
||||
&& member.jid.indexOf(this.moderator.getFocusUserJid() + "/") == 0) {
|
||||
member.isFocus = true;
|
||||
}
|
||||
|
||||
pres.find(">x").remove();
|
||||
$(pres).find(">x").remove();
|
||||
var nodes = [];
|
||||
parser.packet2JSON(pres, nodes);
|
||||
for(var i = 0; i < nodes.length; i++)
|
||||
|
@ -206,7 +233,7 @@ ChatRoom.prototype.onPresence = function (pres) {
|
|||
}
|
||||
break;
|
||||
default :
|
||||
this.processNode(node);
|
||||
this.processNode(node, from);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -218,7 +245,7 @@ ChatRoom.prototype.onPresence = function (pres) {
|
|||
this.role = member.role;
|
||||
|
||||
this.eventEmitter.emit(XMPPEvents.LOCAL_ROLE_CHANGED,
|
||||
member, Moderator.isModerator());
|
||||
member, this.isModerator());
|
||||
}
|
||||
if (!this.joined) {
|
||||
this.joined = true;
|
||||
|
@ -257,8 +284,9 @@ ChatRoom.prototype.onPresence = function (pres) {
|
|||
|
||||
};
|
||||
|
||||
ChatRoom.prototype.processNode = function (node) {
|
||||
this.eventEmitter.emit(XMPPEvents.PRESENCE_SETTING, node);
|
||||
ChatRoom.prototype.processNode = function (node, from) {
|
||||
if(this.presHandlers[node.tagName])
|
||||
this.presHandlers[node.tagName](node, from);
|
||||
};
|
||||
|
||||
ChatRoom.prototype.sendMessage = function (body, nickname) {
|
||||
|
@ -283,9 +311,7 @@ ChatRoom.prototype.onParticipantLeft = function (jid) {
|
|||
|
||||
this.eventEmitter.emit(XMPPEvents.MUC_MEMBER_LEFT, jid);
|
||||
|
||||
this.connection.jingle.terminateByJid(jid);
|
||||
|
||||
Moderator.onMucMemberLeft(jid);
|
||||
this.moderator.onMucMemberLeft(jid);
|
||||
};
|
||||
|
||||
ChatRoom.prototype.onPresenceUnavailable = function (pres, from) {
|
||||
|
@ -447,6 +473,14 @@ ChatRoom.prototype.removeFromPresence = function (key) {
|
|||
}
|
||||
};
|
||||
|
||||
ChatRoom.prototype.addPresenceListener = function (name, handler) {
|
||||
this.presHandlers[name] = handler;
|
||||
}
|
||||
|
||||
ChatRoom.prototype.removePresenceListener = function (name) {
|
||||
delete this.presHandlers[name];
|
||||
}
|
||||
|
||||
ChatRoom.prototype.isModerator = function (jid) {
|
||||
return this.role === 'moderator';
|
||||
};
|
||||
|
@ -466,21 +500,18 @@ module.exports = function(XMPP) {
|
|||
init: function (conn) {
|
||||
this.connection = conn;
|
||||
// add handlers (just once)
|
||||
this.connection.addHandler(this.onPresence.bind(this), null, 'presence', null, null);
|
||||
this.connection.addHandler(this.onPresence.bind(this), null, 'presence', null, null, null, null);
|
||||
this.connection.addHandler(this.onPresenceUnavailable.bind(this), null, 'presence', 'unavailable', null);
|
||||
this.connection.addHandler(this.onPresenceError.bind(this), null, 'presence', 'error', null);
|
||||
this.connection.addHandler(this.onMessage.bind(this), null, 'message', null, null);
|
||||
},
|
||||
doJoin: function (jid, password, eventEmitter) {
|
||||
createRoom: function (jid, password, eventEmitter) {
|
||||
var roomJid = Strophe.getBareJidFromJid(jid);
|
||||
if(this.rooms[roomJid])
|
||||
{
|
||||
if (this.rooms[roomJid]) {
|
||||
console.error("You are already in the room!");
|
||||
return;
|
||||
}
|
||||
this.rooms[roomJid] = new ChatRoom(this.connection, jid, password, XMPP, eventEmitter);
|
||||
|
||||
this.rooms[roomJid].sendPresence();
|
||||
return this.rooms[roomJid];
|
||||
},
|
||||
doLeave: function (jid) {
|
||||
|
|
|
@ -11,7 +11,6 @@ module.exports = function(XMPP, eventEmitter) {
|
|||
sessions: {},
|
||||
jid2session: {},
|
||||
ice_config: {iceServers: []},
|
||||
activecall: null,
|
||||
media_constraints: {
|
||||
mandatory: {
|
||||
'OfferToReceiveAudio': true,
|
||||
|
@ -108,7 +107,7 @@ module.exports = function(XMPP, eventEmitter) {
|
|||
sess.media_constraints = this.media_constraints;
|
||||
sess.ice_config = this.ice_config;
|
||||
|
||||
sess.initialize(fromJid, false);
|
||||
sess.initialize(Strophe.getBareJidFromJid(fromJid), false);
|
||||
// FIXME: setRemoteDescription should only be done when this call is to be accepted
|
||||
sess.setOffer($(iq).find('>jingle'));
|
||||
|
||||
|
@ -119,21 +118,14 @@ module.exports = function(XMPP, eventEmitter) {
|
|||
// .sendAnswer and .accept
|
||||
// or .sendTerminate -- not necessarily synchronous
|
||||
|
||||
// TODO: do we check activecall == null?
|
||||
this.connection.jingle.activecall = sess;
|
||||
|
||||
eventEmitter.emit(XMPPEvents.CALL_INCOMING, sess);
|
||||
|
||||
// TODO: check affiliation and/or role
|
||||
console.log('emuc data for', sess.peerjid,
|
||||
this.connection.emuc.members[sess.peerjid]);
|
||||
sess.sendAnswer();
|
||||
sess.accept();
|
||||
break;
|
||||
case 'session-accept':
|
||||
sess.setAnswer($(iq).find('>jingle'));
|
||||
sess.accept();
|
||||
$(document).trigger('callaccepted.jingle', [sess.sid]);
|
||||
break;
|
||||
case 'session-terminate':
|
||||
// If this is not the focus sending the terminate, we have
|
||||
|
@ -188,21 +180,6 @@ module.exports = function(XMPP, eventEmitter) {
|
|||
}
|
||||
return true;
|
||||
},
|
||||
initiate: function (peerjid, myjid) { // initiate a new jinglesession to peerjid
|
||||
var sess = new JingleSession(myjid || this.connection.jid,
|
||||
Math.random().toString(36).substr(2, 12), // random string
|
||||
this.connection, XMPP, eventEmitter);
|
||||
// configure session
|
||||
|
||||
sess.media_constraints = this.media_constraints;
|
||||
sess.ice_config = this.ice_config;
|
||||
|
||||
sess.initialize(peerjid, true);
|
||||
this.sessions[sess.sid] = sess;
|
||||
this.jid2session[sess.peerjid] = sess;
|
||||
sess.sendOffer();
|
||||
return sess;
|
||||
},
|
||||
terminate: function (sid, reason, text) { // terminate by sessionid (or all sessions)
|
||||
if (sid === null || sid === undefined) {
|
||||
for (sid in this.sessions) {
|
||||
|
@ -222,34 +199,6 @@ module.exports = function(XMPP, eventEmitter) {
|
|||
delete this.sessions[sid];
|
||||
}
|
||||
},
|
||||
// Used to terminate a session when an unavailable presence is received.
|
||||
terminateByJid: function (jid) {
|
||||
if (this.jid2session.hasOwnProperty(jid)) {
|
||||
var sess = this.jid2session[jid];
|
||||
if (sess) {
|
||||
sess.terminate();
|
||||
console.log('peer went away silently', jid);
|
||||
delete this.sessions[sess.sid];
|
||||
delete this.jid2session[jid];
|
||||
$(document).trigger('callterminated.jingle',
|
||||
[sess.sid, jid], 'gone');
|
||||
}
|
||||
}
|
||||
},
|
||||
terminateRemoteByJid: function (jid, reason) {
|
||||
if (this.jid2session.hasOwnProperty(jid)) {
|
||||
var sess = this.jid2session[jid];
|
||||
if (sess) {
|
||||
sess.sendTerminate(reason || (!sess.active()) ? 'kick' : null);
|
||||
sess.terminate();
|
||||
console.log('terminate peer with jid', sess.sid, jid);
|
||||
delete this.sessions[sess.sid];
|
||||
delete this.jid2session[jid];
|
||||
$(document).trigger('callterminated.jingle',
|
||||
[sess.sid, jid, 'kicked']);
|
||||
}
|
||||
}
|
||||
},
|
||||
getStunAndTurnCredentials: function () {
|
||||
// get stun and turn configuration from server via xep-0215
|
||||
// uses time-limited credentials as described in
|
||||
|
|
|
@ -23,7 +23,7 @@ function createConnection(bosh) {
|
|||
function initStrophePlugins(XMPP)
|
||||
{
|
||||
require("./strophe.emuc")(XMPP);
|
||||
// require("./strophe.jingle")(XMPP, eventEmitter);
|
||||
require("./strophe.jingle")(XMPP, XMPP.eventEmitter);
|
||||
// require("./strophe.moderate")(XMPP, eventEmitter);
|
||||
require("./strophe.util")();
|
||||
require("./strophe.rayo")();
|
||||
|
@ -52,7 +52,6 @@ function initStrophePlugins(XMPP)
|
|||
//}
|
||||
|
||||
function XMPP(options) {
|
||||
this.sessionTerminated = false;
|
||||
this.eventEmitter = new EventEmitter();
|
||||
this.connection = null;
|
||||
this.disconnectInProgress = false;
|
||||
|
@ -61,9 +60,8 @@ function XMPP(options) {
|
|||
this.options = options;
|
||||
initStrophePlugins(this);
|
||||
// registerListeners();
|
||||
Moderator.init(this, this.eventEmitter);
|
||||
|
||||
this.connection = createConnection(options.bosh);
|
||||
Moderator.setConnection(this.connection);
|
||||
}
|
||||
|
||||
|
||||
|
@ -118,7 +116,7 @@ XMPP.prototype._connect = function (jid, password) {
|
|||
if (self.connection && self.connection.connected &&
|
||||
Strophe.getResourceFromJid(self.connection.jid)) {
|
||||
// .connected is true while connecting?
|
||||
self.connection.send($pres());
|
||||
// self.connection.send($pres());
|
||||
self.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_ESTABLISHED,
|
||||
Strophe.getResourceFromJid(self.connection.jid));
|
||||
}
|
||||
|
@ -167,8 +165,8 @@ XMPP.prototype.connect = function (jid, password) {
|
|||
return this._connect(jid, password);
|
||||
};
|
||||
|
||||
XMPP.prototype.joinRoom = function(roomName, useNicks, nick) {
|
||||
var roomjid = roomName + '@' + Strophe.getDomainFromJid(this.connection.jid);
|
||||
XMPP.prototype.createRoom = function (roomName, useNicks, nick) {
|
||||
var roomjid = roomName + '@' + this.options.hosts.muc;
|
||||
|
||||
if (useNicks) {
|
||||
if (nick) {
|
||||
|
@ -184,32 +182,9 @@ XMPP.prototype.joinRoom = function(roomName, useNicks, nick) {
|
|||
|
||||
roomjid += '/' + tmpJid;
|
||||
}
|
||||
return this.connection.emuc.doJoin(roomjid, null, this.eventEmitter);
|
||||
};
|
||||
|
||||
|
||||
XMPP.prototype.disposeConference = function (onUnload) {
|
||||
var handler = this.connection.jingle.activecall;
|
||||
if (handler && handler.peerconnection) {
|
||||
// FIXME: probably removing streams is not required and close() should
|
||||
// be enough
|
||||
if (RTC.localAudio) {
|
||||
handler.peerconnection.removeStream(
|
||||
RTC.localAudio.getOriginalStream(), onUnload);
|
||||
}
|
||||
if (RTC.localVideo) {
|
||||
handler.peerconnection.removeStream(
|
||||
RTC.localVideo.getOriginalStream(), onUnload);
|
||||
}
|
||||
handler.peerconnection.close();
|
||||
}
|
||||
this.eventEmitter.emit(XMPPEvents.DISPOSE_CONFERENCE, onUnload);
|
||||
this.connection.jingle.activecall = null;
|
||||
if (!onUnload) {
|
||||
this.sessionTerminated = true;
|
||||
this.connection.emuc.doLeave();
|
||||
}
|
||||
};
|
||||
return this.connection.emuc.createRoom(roomjid, null, this.eventEmitter);
|
||||
}
|
||||
|
||||
XMPP.prototype.addListener = function(type, listener) {
|
||||
this.eventEmitter.on(type, listener);
|
||||
|
@ -220,34 +195,24 @@ XMPP.prototype.removeListener = function (type, listener) {
|
|||
};
|
||||
|
||||
XMPP.prototype.leaveRoom = function (jid) {
|
||||
var handler = this.connection.jingle.jid2session[jid];
|
||||
if (handler && handler.peerconnection) {
|
||||
// FIXME: probably removing streams is not required and close() should
|
||||
// be enough
|
||||
if (RTC.localAudio) {
|
||||
handler.peerconnection.removeStream(
|
||||
RTC.localAudio.getOriginalStream(), true);
|
||||
}
|
||||
if (RTC.localVideo) {
|
||||
handler.peerconnection.removeStream(
|
||||
RTC.localVideo.getOriginalStream(), true);
|
||||
}
|
||||
handler.peerconnection.close();
|
||||
}
|
||||
this.eventEmitter.emit(XMPPEvents.DISPOSE_CONFERENCE);
|
||||
this.connection.emuc.doLeave(jid);
|
||||
};
|
||||
|
||||
|
||||
XMPP.prototype.allocateConferenceFocus = function(roomName, callback) {
|
||||
Moderator.allocateConferenceFocus(roomName, callback);
|
||||
};
|
||||
|
||||
XMPP.prototype.getLoginUrl = function (roomName, callback) {
|
||||
Moderator.getLoginUrl(roomName, callback);
|
||||
}
|
||||
|
||||
XMPP.prototype.getPopupLoginUrl = function (roomName, callback) {
|
||||
Moderator.getPopupLoginUrl(roomName, callback);
|
||||
};
|
||||
|
||||
XMPP.prototype.isModerator = function () {
|
||||
return Moderator.isModerator();
|
||||
};
|
||||
|
||||
XMPP.prototype.isSipGatewayEnabled = function () {
|
||||
return Moderator.isSipGatewayEnabled();
|
||||
}
|
||||
|
||||
XMPP.prototype.isExternalAuthEnabled = function () {
|
||||
return Moderator.isExternalAuthEnabled();
|
||||
};
|
||||
|
||||
XMPP.prototype.isConferenceInProgress = function () {
|
||||
return this.connection && this.connection.jingle.activecall &&
|
||||
this.connection.jingle.activecall.peerconnection;
|
||||
|
@ -376,10 +341,6 @@ XMPP.prototype.eject = function (jid) {
|
|||
this.connection.moderate.eject(jid);
|
||||
};
|
||||
|
||||
XMPP.prototype.logout = function (callback) {
|
||||
Moderator.logout(callback);
|
||||
};
|
||||
|
||||
XMPP.prototype.getJidFromSSRC = function (ssrc) {
|
||||
if (!this.isConferenceInProgress())
|
||||
return null;
|
||||
|
@ -396,7 +357,7 @@ XMPP.prototype.removeStream = function (stream) {
|
|||
this.connection.jingle.activecall.peerconnection.removeStream(stream);
|
||||
};
|
||||
|
||||
XMPP.prototype.disconnect = function (callback) {
|
||||
XMPP.prototype.disconnect = function () {
|
||||
if (this.disconnectInProgress || !this.connection || !this.connection.connected)
|
||||
{
|
||||
this.eventEmitter.emit(JitsiConnectionEvents.WRONG_STATE);
|
||||
|
|
|
@ -49,6 +49,7 @@ var XMPPEvents = {
|
|||
ROOM_JOIN_ERROR: 'xmpp.room_join_error',
|
||||
ROOM_CONNECT_ERROR: 'xmpp.room_connect_error',
|
||||
// xmpp is connected and obtained user media
|
||||
READY_TO_JOIN: 'xmpp.ready_to_join'
|
||||
READY_TO_JOIN: 'xmpp.ready_to_join',
|
||||
FOCUS_LEFT: "xmpp.focus_left"
|
||||
};
|
||||
module.exports = XMPPEvents;
|
Loading…
Reference in New Issue