Selaa lähdekoodia

Fixes join and leave methods. Adds communication with jicofo. Implements custom commands methods.

dev1
hristoterezov 10 vuotta sitten
vanhempi
commit
e9cf303fa6

+ 44
- 18
JitsiConference.js Näytä tiedosto

@@ -1,5 +1,3 @@
1
-var room = null;
2
-
3 1
 
4 2
 /**
5 3
  * Creates a JitsiConference object with the given name and properties.
@@ -15,13 +13,16 @@ function JitsiConference(options) {
15 13
     this.options = options;
16 14
     this.connection = this.options.connection;
17 15
     this.xmpp = this.connection.xmpp;
16
+    this.room = this.xmpp.createRoom(this.options.name, null, null);
18 17
 }
19 18
 
20 19
 /**
21 20
  * Joins the conference.
21
+ * @param password {string} the password
22 22
  */
23
-JitsiConference.prototype.join = function () {
24
-    room = this.xmpp.joinRoom(this.options.name, null, null);
23
+JitsiConference.prototype.join = function (password) {
24
+
25
+    this.room.joinRoom(password);
25 26
 }
26 27
 
27 28
 /**
@@ -29,7 +30,7 @@ JitsiConference.prototype.join = function () {
29 30
  */
30 31
 JitsiConference.prototype.leave = function () {
31 32
     this.xmpp.leaveRoom(room.roomjid);
32
-    room = null;
33
+    this.room = null;
33 34
 }
34 35
 
35 36
 /**
@@ -60,7 +61,7 @@ JitsiConference.prototype.getLocalTracks = function () {
60 61
  * Note: consider adding eventing functionality by extending an EventEmitter impl, instead of rolling ourselves
61 62
  */
62 63
 JitsiConference.prototype.on = function (eventId, handler) {
63
-    this.xmpp.addListener(eventId, handler);
64
+    this.add.addListener(eventId, handler);
64 65
 }
65 66
 
66 67
 /**
@@ -71,7 +72,7 @@ JitsiConference.prototype.on = function (eventId, handler) {
71 72
  * Note: consider adding eventing functionality by extending an EventEmitter impl, instead of rolling ourselves
72 73
  */
73 74
 JitsiConference.prototype.off = function (eventId, handler) {
74
-    this.xmpp.removeListener(event, listener);
75
+    this.room.removeListener(eventId, listener);
75 76
 }
76 77
 
77 78
 // Common aliases for event emitter
@@ -84,7 +85,7 @@ JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off
84 85
  * @param handler {Function} handler for the command
85 86
  */
86 87
  JitsiConference.prototype.addCommandListener = function (command, handler) {
87
-
88
+     this.room.addPresenceListener(command, handler);
88 89
  }
89 90
 
90 91
 /**
@@ -92,7 +93,7 @@ JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off
92 93
   * @param command {String}  the name of the command
93 94
   */
94 95
  JitsiConference.prototype.removeCommandListener = function (command) {
95
-
96
+    this.room.removePresenceListener(command);
96 97
  }
97 98
 
98 99
 /**
@@ -100,21 +101,37 @@ JitsiConference.prototype.removeEventListener = JitsiConference.prototype.off
100 101
  * @param message the text message.
101 102
  */
102 103
 JitsiConference.prototype.sendTextMessage = function (message) {
103
-    room.send
104
+    this.room.sendMessage(message);
104 105
 }
105 106
 
106 107
 /**
107 108
  * Send presence command.
108 109
  * @param name the name of the command.
109 110
  * @param values Object with keys and values that will be send.
110
- * @param persistent if false the command will be sent only one time
111
- * @param successCallback will be called when the command is successfully send.
112
- * @param errorCallback will be called when the command is not sent successfully.
113
- * @returns {Promise.<{void}, JitsiConferenceError>} A promise that returns an array of created streams if resolved,
114
- *     or an JitsiConferenceError if rejected.
115
- */
116
-JitsiConference.prototype.sendCommand = function (name, values, persistent) {
111
+ **/
112
+JitsiConference.prototype.sendCommand = function (name, values) {
113
+    this.room.addToPresence(name, values);
114
+    this.room.sendPresence();
115
+}
116
+
117
+/**
118
+ * Send presence command one time.
119
+ * @param name the name of the command.
120
+ * @param values Object with keys and values that will be send.
121
+ **/
122
+JitsiConference.prototype.sendCommandOnce = function (name, values) {
123
+    this.sendCommand(name, values);
124
+    this.removeCommand(name);
125
+}
117 126
 
127
+/**
128
+ * Send presence command.
129
+ * @param name the name of the command.
130
+ * @param values Object with keys and values that will be send.
131
+ * @param persistent if false the command will be sent only one time
132
+ **/
133
+JitsiConference.prototype.removeCommand = function (name) {
134
+    this.room.removeFromPresence(name);
118 135
 }
119 136
 
120 137
 /**
@@ -122,7 +139,7 @@ JitsiConference.prototype.sendCommand = function (name, values, persistent) {
122 139
  * @param name the display name to set
123 140
  */
124 141
 JitsiConference.prototype.setDisplayName = function(name) {
125
-    room.addToPresence("nick", {attributes: {xmlns: 'http://jabber.org/protocol/nick'}, value: name});
142
+    this.room.addToPresence("nick", {attributes: {xmlns: 'http://jabber.org/protocol/nick'}, value: name});
126 143
 }
127 144
 
128 145
 /**
@@ -141,5 +158,14 @@ JitsiConference.prototype.getParticipants = function() {
141 158
 
142 159
 }
143 160
 
161
+/**
162
+ * @returns {JitsiParticipant} the participant in this conference with the specified id (or
163
+ * null if there isn't one).
164
+ * @param id the id of the participant.
165
+ */
166
+JitsiConference.prototype.getParticipantById = function(id) {
167
+
168
+}
169
+
144 170
 
145 171
 module.exports = JitsiConference;

+ 9
- 1
JitsiConferenceEvents.js Näytä tiedosto

@@ -62,7 +62,15 @@ var JitsiConferenceEvents = {
62 62
     /**
63 63
      * Indicates that the connection to the conference has been restored.
64 64
      */
65
-    CONNECTION_ESTABLISHED: "conference.connecionEstablished"
65
+    CONNECTION_RESTORED: "conference.connecionRestored",
66
+    /**
67
+     * Indicates that conference has been joined.
68
+     */
69
+    CONFERENCE_JOINED: "conference.joined",
70
+    /**
71
+     * Indicates that conference has been left.
72
+     */
73
+    CONFERENCE_LEFT: "conference.left"
66 74
 };
67 75
 
68 76
 module.exports = JitsiConferenceEvents;

+ 3
- 6
JitsiConnection.js Näytä tiedosto

@@ -1,11 +1,6 @@
1 1
 var JitsiConference = require("./JitsiConference");
2 2
 var XMPP = require("./modules/xmpp/xmpp");
3 3
 
4
-function wrapper()
5
-{
6
-    var jitsiconnectioninstance = new JitsiConnection();
7
-    this.a = jitsiconnectioninstance.a();
8
-}
9 4
 /**
10 5
  * Creates new connection object for the Jitsi Meet server side video conferencing service. Provides access to the
11 6
  * JitsiConference interface.
@@ -20,6 +15,7 @@ function JitsiConnection(appID, token, options) {
20 15
     this.token = token;
21 16
     this.options = options;
22 17
     this.xmpp = new XMPP(options);
18
+    this.conferences = {};
23 19
 }
24 20
 
25 21
 /**
@@ -54,7 +50,8 @@ JitsiConnection.prototype.setToken = function (token) {
54 50
  * @returns {JitsiConference} returns the new conference object.
55 51
  */
56 52
 JitsiConnection.prototype.initJitsiConference = function (name, options) {
57
-    return new JitsiConference({name: name, config: options, connection: this});
53
+    this.conferences[name] = new JitsiConference({name: name, config: options, connection: this});
54
+    return this.conferences[name];
58 55
 }
59 56
 
60 57
 /**

+ 135
- 0
JitsiParticipant.js Näytä tiedosto

@@ -0,0 +1,135 @@
1
+/**
2
+ * Represents a participant in (a member of) a conference.
3
+ */
4
+function JitsiParticipant(){
5
+
6
+}
7
+
8
+/**
9
+ * @returns {JitsiConference} The conference that this participant belongs to.
10
+ */
11
+JitsiParticipant.prototype.getConference = function() {
12
+
13
+}
14
+
15
+/**
16
+ * @returns {Array.<JitsiTrack>} The list of media tracks for this participant.
17
+ */
18
+JitsiParticipant.prototype.getTracks = function() {
19
+
20
+}
21
+
22
+/**
23
+ * @returns {String} The ID (i.e. JID) of this participant.
24
+ */
25
+JitsiParticipant.prototype.getId = function() {
26
+
27
+}
28
+
29
+/**
30
+ * @returns {String} The human-readable display name of this participant.
31
+ */
32
+JitsiParticipant.prototype.getDisplayName = function() {
33
+
34
+}
35
+
36
+/**
37
+ * @returns {Boolean} Whether this participant is a moderator or not.
38
+ */
39
+JitsiParticipant.prototype.isModerator = function() {
40
+
41
+}
42
+
43
+// Gets a link to an etherpad instance advertised by the participant?
44
+//JitsiParticipant.prototype.getEtherpad = function() {
45
+//
46
+//}
47
+
48
+
49
+/*
50
+ * @returns {Boolean} Whether this participant has muted their audio.
51
+ */
52
+JitsiParticipant.prototype.isAudioMuted = function() {
53
+
54
+}
55
+
56
+/*
57
+ * @returns {Boolean} Whether this participant has muted their video.
58
+ */
59
+JitsiParticipant.prototype.isVideoMuted = function() {
60
+
61
+}
62
+
63
+/*
64
+ * @returns {???} The latest statistics reported by this participant (i.e. info used to populate the GSM bars)
65
+ * TODO: do we expose this or handle it internally?
66
+ */
67
+JitsiParticipant.prototype.getLatestStats = function() {
68
+
69
+}
70
+
71
+/**
72
+ * @returns {String} The role of this participant.
73
+ */
74
+JitsiParticipant.prototype.getRole = function() {
75
+
76
+}
77
+
78
+/*
79
+ * @returns {Boolean} Whether this participant is the conference focus (i.e. jicofo).
80
+ */
81
+JitsiParticipant.prototype.isFocus = function() {
82
+
83
+}
84
+
85
+/*
86
+ * @returns {Boolean} Whether this participant is a conference recorder (i.e. jirecon).
87
+ */
88
+JitsiParticipant.prototype.isRecorder = function() {
89
+
90
+}
91
+
92
+/*
93
+ * @returns {Boolean} Whether this participant is a SIP gateway (i.e. jigasi).
94
+ */
95
+JitsiParticipant.prototype.isSipGateway = function() {
96
+
97
+}
98
+
99
+/**
100
+ * @returns {String} The ID for this participant's avatar.
101
+ */
102
+JitsiParticipant.prototype.getAvatarId = function() {
103
+
104
+}
105
+
106
+/**
107
+ * @returns {Boolean} Whether this participant is currently sharing their screen.
108
+ */
109
+JitsiParticipant.prototype.isScreenSharing = function() {
110
+
111
+}
112
+
113
+/**
114
+ * @returns {String} The user agent of this participant (i.e. browser userAgent string).
115
+ */
116
+JitsiParticipant.prototype.getUserAgent = function() {
117
+
118
+}
119
+
120
+/**
121
+ * Kicks the participant from the conference (requires certain privileges).
122
+ */
123
+JitsiParticipant.prototype.kick = function() {
124
+
125
+}
126
+
127
+/**
128
+ * Asks this participant to mute themselves.
129
+ */
130
+JitsiParticipant.prototype.askToMute = function() {
131
+
132
+}
133
+
134
+
135
+module.exports = JitsiParticipant();

+ 1
- 1
JitsiTrack.js Näytä tiedosto

@@ -26,7 +26,7 @@ JitsiTrack.prototype.getType = function() {
26 26
 };
27 27
 
28 28
 /**
29
- * Returns the JitsiParticipant to which this track belongs, or null if it is a local track.
29
+ * @returns {JitsiParticipant} to which this track belongs, or null if it is a local track.
30 30
  */
31 31
 JitsiTrack.prototype.getParitcipant() = function() {
32 32
 

+ 14152
- 8072
lib-jitsi-meet.js
File diff suppressed because it is too large
Näytä tiedosto


+ 5492
- 0
libs/strophe/strophe.js
File diff suppressed because it is too large
Näytä tiedosto


+ 14
- 6
modules/settings/Settings.js Näytä tiedosto

@@ -21,17 +21,17 @@ function Settings(conferenceID) {
21 21
     this.userId;
22 22
     this.language = null;
23 23
     this.confSettings = null;
24
+    this.conferenceID = conferenceID;
24 25
     if (supportsLocalStorage()) {
25
-        if(!window.localStorage.jitsiConferences)
26
-            window.localStorage.jitsiConferences = {}
27
-        if (!window.localStorage.jitsiConferences[conferenceID]) {
28
-            window.localStorage.jitsiConferences[conferenceID] = {}
29
-        }
30
-        this.confSettings = window.localStorage.jitsiConferences[conferenceID];
26
+        if(!window.localStorage.getItem(conferenceID))
27
+            this.confSettings = {};
28
+        else
29
+            this.confSettings = JSON.parse(window.localStorage.getItem(conferenceID));
31 30
         if(!this.confSettings.jitsiMeetId) {
32 31
             this.confSettings.jitsiMeetId = generateUniqueId();
33 32
             console.log("generated id",
34 33
                 this.confSettings.jitsiMeetId);
34
+            this.save();
35 35
         }
36 36
         this.userId = this.confSettings.jitsiMeetId || '';
37 37
         this.email = this.confSettings.email || '';
@@ -43,16 +43,23 @@ function Settings(conferenceID) {
43 43
     }
44 44
 }
45 45
 
46
+Settings.prototype.save = function () {
47
+    if(!supportsLocalStorage())
48
+        window.localStorage.setItem(this.conferenceID, JSON.stringify(this.confSettings));
49
+}
50
+
46 51
 Settings.prototype.setDisplayName = function (newDisplayName) {
47 52
     this.displayName = newDisplayName;
48 53
     if(this.confSettings != null)
49 54
         this.confSettings.displayname = displayName;
55
+    this.save();
50 56
     return this.displayName;
51 57
 },
52 58
 Settings.prototype.setEmail = function (newEmail) {
53 59
     this.email = newEmail;
54 60
     if(this.confSettings != null)
55 61
         this.confSettings.email = newEmail;
62
+    this.save();
56 63
     return this.email;
57 64
 },
58 65
 Settings.prototype.getSettings = function () {
@@ -67,6 +74,7 @@ Settings.prototype.setLanguage = function (lang) {
67 74
     this.language = lang;
68 75
     if(this.confSettings != null)
69 76
         this.confSettings.language = lang;
77
+    this.save();
70 78
 }
71 79
 
72 80
 module.exports = Settings;

+ 14
- 10
modules/xmpp/JingleSessionPC.js Näytä tiedosto

@@ -9,6 +9,7 @@ var transform = require("sdp-transform");
9 9
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
10 10
 var RTCBrowserType = require("../RTC/RTCBrowserType");
11 11
 var SSRCReplacement = require("./LocalSSRCReplacement");
12
+var RTC = require("../RTC/RTC");
12 13
 
13 14
 // Jingle stuff
14 15
 function JingleSessionPC(me, sid, connection, service, eventEmitter) {
@@ -86,7 +87,7 @@ JingleSessionPC.prototype.doInitialize = function () {
86 87
 
87 88
     this.peerconnection = new TraceablePeerConnection(
88 89
             this.connection.jingle.ice_config,
89
-            APP.RTC.getPCConstraints(),
90
+            RTC.getPCConstraints(),
90 91
             this);
91 92
 
92 93
     this.peerconnection.onicecandidate = function (event) {
@@ -147,15 +148,20 @@ JingleSessionPC.prototype.doInitialize = function () {
147 148
     this.peerconnection.onnegotiationneeded = function (event) {
148 149
         self.eventEmitter.emit(XMPPEvents.PEERCONNECTION_READY, self);
149 150
     };
150
-    // add any local and relayed stream
151
-    APP.RTC.localStreams.forEach(function(stream) {
152
-        self.peerconnection.addStream(stream.getOriginalStream());
153
-    });
151
+
154 152
     this.relayedStreams.forEach(function(stream) {
155 153
         self.peerconnection.addStream(stream);
156 154
     });
157 155
 };
158 156
 
157
+JingleSessionPC.prototype.addLocalStreams = function (localStreams) {
158
+    var self = this;
159
+// add any local and relayed stream
160
+    localStreams.forEach(function(stream) {
161
+        self.peerconnection.addStream(stream.getOriginalStream());
162
+    });
163
+}
164
+
159 165
 function onIceConnectionStateChange(sid, session) {
160 166
     switch (session.peerconnection.iceConnectionState) {
161 167
         case 'checking':
@@ -1307,8 +1313,6 @@ JingleSessionPC.onJingleError = function (session, error)
1307 1313
 
1308 1314
 JingleSessionPC.onJingleFatalError = function (session, error)
1309 1315
 {
1310
-    this.service.sessionTerminated = true;
1311
-    this.connection.emuc.doLeave();
1312 1316
     this.eventEmitter.emit(XMPPEvents.CONFERENCE_SETUP_FAILED);
1313 1317
     this.eventEmitter.emit(XMPPEvents.JINGLE_FATAL_ERROR, session, error);
1314 1318
 }
@@ -1391,7 +1395,7 @@ function sendKeyframe(pc) {
1391 1395
 JingleSessionPC.prototype.remoteStreamAdded = function (data, times) {
1392 1396
     var self = this;
1393 1397
     var thessrc;
1394
-    var streamId = APP.RTC.getStreamID(data.stream);
1398
+    var streamId = RTC.getStreamID(data.stream);
1395 1399
 
1396 1400
     // look up an associated JID for a stream id
1397 1401
     if (!streamId) {
@@ -1426,14 +1430,14 @@ JingleSessionPC.prototype.remoteStreamAdded = function (data, times) {
1426 1430
         }
1427 1431
     }
1428 1432
 
1429
-    APP.RTC.createRemoteStream(data, this.sid, thessrc);
1433
+    RTC.createRemoteStream(data, this.sid, thessrc);
1430 1434
 
1431 1435
     var isVideo = data.stream.getVideoTracks().length > 0;
1432 1436
     // an attempt to work around https://github.com/jitsi/jitmeet/issues/32
1433 1437
     if (isVideo &&
1434 1438
         data.peerjid && this.peerjid === data.peerjid &&
1435 1439
         data.stream.getVideoTracks().length === 0 &&
1436
-        APP.RTC.localVideo.getTracks().length > 0) {
1440
+        RTC.localVideo.getTracks().length > 0) {
1437 1441
         window.setTimeout(function () {
1438 1442
             sendKeyframe(self.peerconnection);
1439 1443
         }, 3000);

+ 354
- 367
modules/xmpp/moderator.js Näytä tiedosto

@@ -6,13 +6,6 @@ var Settings = require("../settings/Settings");
6 6
 var AuthenticationEvents
7 7
     = require("../../service/authentication/AuthenticationEvents");
8 8
 
9
-/**
10
- * Contains logic responsible for enabling/disabling functionality available
11
- * only to moderator users.
12
- */
13
-var connection = null;
14
-var focusUserJid;
15
-
16 9
 function createExpBackoffTimer(step) {
17 10
     var count = 1;
18 11
     return function (reset) {
@@ -28,402 +21,396 @@ function createExpBackoffTimer(step) {
28 21
     };
29 22
 }
30 23
 
31
-var getNextTimeout = createExpBackoffTimer(1000);
32
-var getNextErrorTimeout = createExpBackoffTimer(1000);
24
+
25
+
26
+
27
+
28
+function Moderator(roomName, xmpp, emitter) {
29
+    this.roomName = roomName;
30
+    this.xmppService = xmpp;
31
+    this.getNextTimeout = createExpBackoffTimer(1000);
32
+    this.getNextErrorTimeout = createExpBackoffTimer(1000);
33 33
 // External authentication stuff
34
-var externalAuthEnabled = false;
34
+    this.externalAuthEnabled = false;
35
+    this.settings = new Settings(roomName);
35 36
 // Sip gateway can be enabled by configuring Jigasi host in config.js or
36 37
 // it will be enabled automatically if focus detects the component through
37 38
 // service discovery.
38
-var sipGatewayEnabled = null;
39
-
40
-var eventEmitter = null;
41
-
42
-var Moderator = {
43
-    isModerator: function () {
44
-        return connection && connection.emuc.isModerator();
45
-    },
46
-
47
-    isPeerModerator: function (peerJid) {
48
-        return connection &&
49
-            connection.emuc.getMemberRole(peerJid) === 'moderator';
50
-    },
51
-
52
-    isExternalAuthEnabled: function () {
53
-        return externalAuthEnabled;
54
-    },
55
-
56
-    isSipGatewayEnabled: function () {
57
-        return sipGatewayEnabled;
58
-    },
59
-
60
-    setConnection: function (con) {
61
-        connection = con;
62
-    },
63
-
64
-    init: function (xmpp, emitter) {
65
-        this.xmppService = xmpp;
66
-        sipGatewayEnabled = this.xmppService.options.hosts.call_control !== undefined;
67
-        eventEmitter = emitter;
68
-
69
-        // Message listener that talks to POPUP window
70
-        function listener(event) {
71
-            if (event.data && event.data.sessionId) {
72
-                if (event.origin !== window.location.origin) {
73
-                    console.warn("Ignoring sessionId from different origin: " +
74
-                        event.origin);
75
-                    return;
76
-                }
77
-                localStorage.setItem('sessionId', event.data.sessionId);
78
-                // After popup is closed we will authenticate
39
+    this.sipGatewayEnabled = this.xmppService.options.hosts.call_control !== undefined;
40
+
41
+    this.eventEmitter = emitter;
42
+
43
+    this.connection = this.xmppService.connection;
44
+    this.focusUserJid;
45
+    //FIXME:
46
+    // Message listener that talks to POPUP window
47
+    function listener(event) {
48
+        if (event.data && event.data.sessionId) {
49
+            if (event.origin !== window.location.origin) {
50
+                console.warn("Ignoring sessionId from different origin: " +
51
+                    event.origin);
52
+                return;
79 53
             }
54
+            localStorage.setItem('sessionId', event.data.sessionId);
55
+            // After popup is closed we will authenticate
80 56
         }
81
-        // Register
82
-        if (window.addEventListener) {
83
-            window.addEventListener("message", listener, false);
84
-        } else {
85
-            window.attachEvent("onmessage", listener);
86
-        }
87
-    },
88
-
89
-    onMucMemberLeft: function (jid) {
90
-        console.info("Someone left is it focus ? " + jid);
91
-        var resource = Strophe.getResourceFromJid(jid);
92
-        if (resource === 'focus' && !this.xmppService.sessionTerminated) {
93
-            console.info(
94
-                "Focus has left the room - leaving conference");
95
-            //hangUp();
96
-            // We'd rather reload to have everything re-initialized
97
-            // FIXME: show some message before reload
98
-            location.reload();
99
-        }
100
-    },
101
-    
102
-    setFocusUserJid: function (focusJid) {
103
-        if (!focusUserJid) {
104
-            focusUserJid = focusJid;
105
-            console.info("Focus jid set to: " + focusUserJid);
106
-        }
107
-    },
108
-
109
-    getFocusUserJid: function () {
110
-        return focusUserJid;
111
-    },
112
-
113
-    getFocusComponent: function () {
114
-        // Get focus component address
115
-        var focusComponent = this.xmppService.options.hosts.focus;
116
-        // If not specified use default: 'focus.domain'
117
-        if (!focusComponent) {
118
-            focusComponent = 'focus.' + this.xmppService.options.hosts.domain;
119
-        }
120
-        return focusComponent;
121
-    },
57
+    }
58
+    // Register
59
+    if (window.addEventListener) {
60
+        window.addEventListener("message", listener, false);
61
+    } else {
62
+        window.attachEvent("onmessage", listener);
63
+    }
64
+}
65
+
66
+Moderator.prototype.isExternalAuthEnabled =  function () {
67
+    return this.externalAuthEnabled;
68
+};
122 69
 
123
-    createConferenceIq: function (roomName) {
124
-        // Generate create conference IQ
125
-        var elem = $iq({to: Moderator.getFocusComponent(), type: 'set'});
70
+Moderator.prototype.isSipGatewayEnabled =  function () {
71
+    return this.sipGatewayEnabled;
72
+};
126 73
 
127
-        // Session Id used for authentication
128
-        var sessionId = localStorage.getItem('sessionId');
129
-        var machineUID = Settings.getSettings().uid;
130 74
 
75
+Moderator.prototype.onMucMemberLeft =  function (jid) {
76
+    console.info("Someone left is it focus ? " + jid);
77
+    var resource = Strophe.getResourceFromJid(jid);
78
+    if (resource === 'focus' && !this.xmppService.sessionTerminated) {
131 79
         console.info(
132
-            "Session ID: " + sessionId + " machine UID: " + machineUID);
80
+            "Focus has left the room - leaving conference");
81
+        //hangUp();
82
+        // We'd rather reload to have everything re-initialized
83
+        //FIXME: show some message before reload
84
+        this.eventEmitter.emit(XMPPEvents.FOCUS_LEFT);
85
+    }
86
+};
133 87
 
134
-        elem.c('conference', {
135
-            xmlns: 'http://jitsi.org/protocol/focus',
136
-            room: roomName,
137
-            'machine-uid': machineUID
138
-        });
139 88
 
140
-        if (sessionId) {
141
-            elem.attrs({ 'session-id': sessionId});
142
-        }
89
+Moderator.prototype.setFocusUserJid =  function (focusJid) {
90
+    if (!this.focusUserJid) {
91
+        this.focusUserJid = focusJid;
92
+        console.info("Focus jid set to:  " + this.focusUserJid);
93
+    }
94
+};
143 95
 
144
-        if (this.xmppService.options.hosts.bridge !== undefined) {
145
-            elem.c(
146
-                'property',
147
-                { name: 'bridge', value: this.xmppService.options.hosts.bridge})
148
-                .up();
149
-        }
150
-        // Tell the focus we have Jigasi configured
151
-        if (this.xmppService.options.hosts.call_control !== undefined) {
152
-            elem.c(
153
-                'property',
154
-                { name: 'call_control', value: this.xmppService.options.hosts.call_control})
155
-                .up();
156
-        }
157
-        if (this.xmppService.options.channelLastN !== undefined) {
158
-            elem.c(
159
-                'property',
160
-                { name: 'channelLastN', value: this.xmppService.options.channelLastN})
161
-                .up();
162
-        }
163
-        if (this.xmppService.options.adaptiveLastN !== undefined) {
164
-            elem.c(
165
-                'property',
166
-                { name: 'adaptiveLastN', value: this.xmppService.options.adaptiveLastN})
167
-                .up();
168
-        }
169
-        if (this.xmppService.options.adaptiveSimulcast !== undefined) {
170
-            elem.c(
171
-                'property',
172
-                { name: 'adaptiveSimulcast', value: this.xmppService.options.adaptiveSimulcast})
173
-                .up();
174
-        }
175
-        if (this.xmppService.options.openSctp !== undefined) {
176
-            elem.c(
177
-                'property',
178
-                { name: 'openSctp', value: this.xmppService.options.openSctp})
179
-                .up();
180
-        }
181
-        if(this.xmppService.options.startAudioMuted !== undefined)
182
-        {
183
-            elem.c(
184
-                'property',
185
-                { name: 'startAudioMuted', value: this.xmppService.options.startAudioMuted})
186
-                .up();
187
-        }
188
-        if(this.xmppService.options.startVideoMuted !== undefined)
189
-        {
190
-            elem.c(
191
-                'property',
192
-                { name: 'startVideoMuted', value: this.xmppService.options.startVideoMuted})
193
-                .up();
194
-        }
96
+
97
+Moderator.prototype.getFocusUserJid =  function () {
98
+    return this.focusUserJid;
99
+};
100
+
101
+Moderator.prototype.getFocusComponent =  function () {
102
+    // Get focus component address
103
+    var focusComponent = this.xmppService.options.hosts.focus;
104
+    // If not specified use default:  'focus.domain'
105
+    if (!focusComponent) {
106
+        focusComponent = 'focus.' + this.xmppService.options.hosts.domain;
107
+    }
108
+    return focusComponent;
109
+};
110
+
111
+Moderator.prototype.createConferenceIq =  function () {
112
+    // Generate create conference IQ
113
+    var elem = $iq({to: this.getFocusComponent(), type: 'set'});
114
+
115
+    // Session Id used for authentication
116
+    var sessionId = localStorage.getItem('sessionId');
117
+    var machineUID = this.settings.getSettings().uid;
118
+
119
+    console.info(
120
+            "Session ID: " + sessionId + " machine UID: " + machineUID);
121
+
122
+    elem.c('conference', {
123
+        xmlns: 'http://jitsi.org/protocol/focus',
124
+        room: this.roomName,
125
+        'machine-uid': machineUID
126
+    });
127
+
128
+    if (sessionId) {
129
+        elem.attrs({ 'session-id': sessionId});
130
+    }
131
+    if (this.xmppService.options.hosts.bridge !== undefined) {
195 132
         elem.c(
196 133
             'property',
197
-            { name: 'simulcastMode', value: 'rewriting'})
134
+            {name: 'bridge',value: this.xmppService.options.hosts.bridge})
198 135
             .up();
199
-        elem.up();
200
-        return elem;
201
-    },
202
-
203
-    parseSessionId: function (resultIq) {
204
-        var sessionId = $(resultIq).find('conference').attr('session-id');
205
-        if (sessionId) {
206
-            console.info('Received sessionId: ' + sessionId);
207
-            localStorage.setItem('sessionId', sessionId);
208
-        }
209
-    },
136
+    }
137
+    // Tell the focus we have Jigasi configured
138
+    if (this.xmppService.options.hosts.call_control !== undefined) {
139
+        elem.c(
140
+            'property',
141
+            {name: 'call_control',value:  this.xmppService.options.hosts.call_control})
142
+            .up();
143
+    }
144
+    if (this.xmppService.options.channelLastN !== undefined) {
145
+        elem.c(
146
+            'property',
147
+            {name: 'channelLastN',value: this.xmppService.options.channelLastN})
148
+            .up();
149
+    }
150
+    if (this.xmppService.options.adaptiveLastN !== undefined) {
151
+        elem.c(
152
+            'property',
153
+            {name: 'adaptiveLastN',value: this.xmppService.options.adaptiveLastN})
154
+            .up();
155
+    }
156
+    if (this.xmppService.options.adaptiveSimulcast !== undefined) {
157
+        elem.c(
158
+            'property',
159
+            {name: 'adaptiveSimulcast',value: this.xmppService.options.adaptiveSimulcast})
160
+            .up();
161
+    }
162
+    if (this.xmppService.options.openSctp !== undefined) {
163
+        elem.c(
164
+            'property',
165
+            {name: 'openSctp',value: this.xmppService.options.openSctp})
166
+            .up();
167
+    }
168
+    if(this.xmppService.options.startAudioMuted !== undefined)
169
+    {
170
+        elem.c(
171
+            'property',
172
+            {name: 'startAudioMuted',value: this.xmppService.options.startAudioMuted})
173
+            .up();
174
+    }
175
+    if(this.xmppService.options.startVideoMuted !== undefined)
176
+    {
177
+        elem.c(
178
+            'property',
179
+            {name: 'startVideoMuted',value: this.xmppService.options.startVideoMuted})
180
+            .up();
181
+    }
182
+    elem.c(
183
+        'property',
184
+        {name: 'simulcastMode',value: 'rewriting'})
185
+        .up();
186
+    elem.up();
187
+    return elem;
188
+};
210 189
 
211
-    parseConfigOptions: function (resultIq) {
212 190
 
213
-        Moderator.setFocusUserJid(
214
-            $(resultIq).find('conference').attr('focusjid'));
191
+Moderator.prototype.parseSessionId =  function (resultIq) {
192
+    var sessionId = $(resultIq).find('conference').attr('session-id');
193
+    if (sessionId) {
194
+        console.info('Received sessionId:  ' + sessionId);
195
+        localStorage.setItem('sessionId', sessionId);
196
+    }
197
+};
215 198
 
216
-        var authenticationEnabled
217
-            = $(resultIq).find(
218
-                '>conference>property' +
219
-                '[name=\'authentication\'][value=\'true\']').length > 0;
199
+Moderator.prototype.parseConfigOptions =  function (resultIq) {
220 200
 
221
-        console.info("Authentication enabled: " + authenticationEnabled);
201
+    this.setFocusUserJid(
202
+        $(resultIq).find('conference').attr('focusjid'));
222 203
 
223
-        externalAuthEnabled = $(resultIq).find(
224
-                '>conference>property' +
225
-                '[name=\'externalAuth\'][value=\'true\']').length > 0;
204
+    var authenticationEnabled
205
+        = $(resultIq).find(
206
+            '>conference>property' +
207
+            '[name=\'authentication\'][value=\'true\']').length > 0;
226 208
 
227
-        console.info('External authentication enabled: ' + externalAuthEnabled);
209
+    console.info("Authentication enabled: " + authenticationEnabled);
228 210
 
229
-        if (!externalAuthEnabled) {
230
-            // We expect to receive sessionId in 'internal' authentication mode
231
-            Moderator.parseSessionId(resultIq);
232
-        }
211
+    this.externalAuthEnabled = $(resultIq).find(
212
+            '>conference>property' +
213
+            '[name=\'externalAuth\'][value=\'true\']').length > 0;
233 214
 
234
-        var authIdentity = $(resultIq).find('>conference').attr('identity');
215
+    console.info('External authentication enabled: ' + this.externalAuthEnabled);
235 216
 
236
-        eventEmitter.emit(AuthenticationEvents.IDENTITY_UPDATED,
237
-            authenticationEnabled, authIdentity);
238
-    
239
-        // Check if focus has auto-detected Jigasi component(this will be also
240
-        // included if we have passed our host from the config)
241
-        if ($(resultIq).find(
242
-            '>conference>property' +
243
-            '[name=\'sipGatewayEnabled\'][value=\'true\']').length) {
244
-            sipGatewayEnabled = true;
245
-        }
246
-    
247
-        console.info("Sip gateway enabled: " + sipGatewayEnabled);
248
-    },
249
-
250
-    // FIXME: we need to show the fact that we're waiting for the focus
251
-    // to the user(or that focus is not available)
252
-    allocateConferenceFocus: function (roomName, callback) {
253
-        // Try to use focus user JID from the config
254
-        Moderator.setFocusUserJid(this.xmppService.options.focusUserJid);
255
-        // Send create conference IQ
256
-        var iq = Moderator.createConferenceIq(roomName);
257
-        var self = this;
258
-        connection.sendIQ(
259
-            iq,
260
-            function (result) {
261
-
262
-                // Setup config options
263
-                Moderator.parseConfigOptions(result);
264
-
265
-                if ('true' === $(result).find('conference').attr('ready')) {
266
-                    // Reset both timers
267
-                    getNextTimeout(true);
268
-                    getNextErrorTimeout(true);
269
-                    // Exec callback
270
-                    callback();
271
-                } else {
272
-                    var waitMs = getNextTimeout();
273
-                    console.info("Waiting for the focus... " + waitMs);
274
-                    // Reset error timeout
275
-                    getNextErrorTimeout(true);
276
-                    window.setTimeout(
277
-                        function () {
278
-                            Moderator.allocateConferenceFocus(
279
-                                roomName, callback);
280
-                        }, waitMs);
281
-                }
282
-            },
283
-            function (error) {
284
-                // Invalid session ? remove and try again
285
-                // without session ID to get a new one
286
-                var invalidSession
287
-                    = $(error).find('>error>session-invalid').length;
288
-                if (invalidSession) {
289
-                    console.info("Session expired! - removing");
290
-                    localStorage.removeItem("sessionId");
291
-                }
292
-                if ($(error).find('>error>graceful-shutdown').length) {
293
-                    eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);
294
-                    return;
295
-                }
296
-                // Check for error returned by the reservation system
297
-                var reservationErr = $(error).find('>error>reservation-error');
298
-                if (reservationErr.length) {
299
-                    // Trigger error event
300
-                    var errorCode = reservationErr.attr('error-code');
301
-                    var errorMsg;
302
-                    if ($(error).find('>error>text')) {
303
-                        errorMsg = $(error).find('>error>text').text();
304
-                    }
305
-                    eventEmitter.emit(
306
-                        XMPPEvents.RESERVATION_ERROR, errorCode, errorMsg);
307
-                    return;
308
-                }
309
-                // Not authorized to create new room
310
-                if ($(error).find('>error>not-authorized').length) {
311
-                    console.warn("Unauthorized to start the conference", error);
312
-                    var toDomain
313
-                        = Strophe.getDomainFromJid(error.getAttribute('to'));
314
-                    if (toDomain !== this.xmppService.options.hosts.anonymousdomain) {
315
-                        // FIXME: "is external" should come either from
316
-                        // the focus or config.js
317
-                        externalAuthEnabled = true;
318
-                    }
319
-                    eventEmitter.emit(
320
-                        XMPPEvents.AUTHENTICATION_REQUIRED,
321
-                        function () {
322
-                            Moderator.allocateConferenceFocus(
323
-                                roomName, callback);
324
-                        });
325
-                    return;
326
-                }
327
-                var waitMs = getNextErrorTimeout();
328
-                console.error("Focus error, retry after " + waitMs, error);
329
-                // Show message
330
-                var focusComponent = Moderator.getFocusComponent();
331
-                var retrySec = waitMs / 1000;
332
-                // FIXME: message is duplicated ?
333
-                // Do not show in case of session invalid
334
-                // which means just a retry
335
-                if (!invalidSession) {
336
-                    eventEmitter.emit(XMPPEvents.FOCUS_DISCONNECTED,
337
-                        focusComponent, retrySec);
338
-                }
339
-                // Reset response timeout
340
-                getNextTimeout(true);
217
+    if (!this.externalAuthEnabled) {
218
+        // We expect to receive sessionId in 'internal' authentication mode
219
+        this.parseSessionId(resultIq);
220
+    }
221
+
222
+    var authIdentity = $(resultIq).find('>conference').attr('identity');
223
+
224
+    this.eventEmitter.emit(AuthenticationEvents.IDENTITY_UPDATED,
225
+        authenticationEnabled, authIdentity);
226
+
227
+    // Check if focus has auto-detected Jigasi component(this will be also
228
+    // included if we have passed our host from the config)
229
+    if ($(resultIq).find(
230
+        '>conference>property' +
231
+        '[name=\'sipGatewayEnabled\'][value=\'true\']').length) {
232
+        this.sipGatewayEnabled = true;
233
+    }
234
+
235
+    console.info("Sip gateway enabled:  " + this.sipGatewayEnabled);
236
+};
237
+
238
+// FIXME =  we need to show the fact that we're waiting for the focus
239
+// to the user(or that focus is not available)
240
+Moderator.prototype.allocateConferenceFocus =  function ( callback) {
241
+    // Try to use focus user JID from the config
242
+    this.setFocusUserJid(this.xmppService.options.focusUserJid);
243
+    // Send create conference IQ
244
+    var iq = this.createConferenceIq();
245
+    var self = this;
246
+    this.connection.sendIQ(
247
+        iq,
248
+        function (result) {
249
+
250
+            // Setup config options
251
+            self.parseConfigOptions(result);
252
+
253
+            if ('true' === $(result).find('conference').attr('ready')) {
254
+                // Reset both timers
255
+                self.getNextTimeout(true);
256
+                self.getNextErrorTimeout(true);
257
+                // Exec callback
258
+                callback();
259
+            } else {
260
+                var waitMs = self.getNextTimeout();
261
+                console.info("Waiting for the focus... " + waitMs);
262
+                // Reset error timeout
263
+                self.getNextErrorTimeout(true);
341 264
                 window.setTimeout(
342 265
                     function () {
343
-                        Moderator.allocateConferenceFocus(roomName, callback);
266
+                        self.allocateConferenceFocus(callback);
344 267
                     }, waitMs);
345 268
             }
346
-        );
347
-    },
348
-
349
-    getLoginUrl: function (roomName, urlCallback) {
350
-        var iq = $iq({to: Moderator.getFocusComponent(), type: 'get'});
351
-        iq.c('login-url', {
352
-            xmlns: 'http://jitsi.org/protocol/focus',
353
-            room: roomName,
354
-            'machine-uid': Settings.getSettings().uid
355
-        });
356
-        connection.sendIQ(
357
-            iq,
358
-            function (result) {
359
-                var url = $(result).find('login-url').attr('url');
360
-                url = url = decodeURIComponent(url);
361
-                if (url) {
362
-                    console.info("Got auth url: " + url);
363
-                    urlCallback(url);
364
-                } else {
365
-                    console.error(
366
-                        "Failed to get auth url from the focus", result);
269
+        },
270
+        function (error) {
271
+            // Invalid session ? remove and try again
272
+            // without session ID to get a new one
273
+            var invalidSession
274
+                = $(error).find('>error>session-invalid').length;
275
+            if (invalidSession) {
276
+                console.info("Session expired! - removing");
277
+                localStorage.removeItem("sessionId");
278
+            }
279
+            if ($(error).find('>error>graceful-shutdown').length) {
280
+                self.eventEmitter.emit(XMPPEvents.GRACEFUL_SHUTDOWN);
281
+                return;
282
+            }
283
+            // Check for error returned by the reservation system
284
+            var reservationErr = $(error).find('>error>reservation-error');
285
+            if (reservationErr.length) {
286
+                // Trigger error event
287
+                var errorCode = reservationErr.attr('error-code');
288
+                var errorMsg;
289
+                if ($(error).find('>error>text')) {
290
+                    errorMsg = $(error).find('>error>text').text();
367 291
                 }
368
-            },
369
-            function (error) {
370
-                console.error("Get auth url error", error);
292
+                self.eventEmitter.emit(
293
+                    XMPPEvents.RESERVATION_ERROR, errorCode, errorMsg);
294
+                return;
371 295
             }
372
-        );
373
-    },
374
-    getPopupLoginUrl: function (roomName, urlCallback) {
375
-        var iq = $iq({to: Moderator.getFocusComponent(), type: 'get'});
376
-        iq.c('login-url', {
377
-            xmlns: 'http://jitsi.org/protocol/focus',
378
-            room: roomName,
379
-            'machine-uid': Settings.getSettings().uid,
380
-            popup: true
381
-        });
382
-        connection.sendIQ(
383
-            iq,
384
-            function (result) {
385
-                var url = $(result).find('login-url').attr('url');
386
-                url = url = decodeURIComponent(url);
387
-                if (url) {
388
-                    console.info("Got POPUP auth url: " + url);
389
-                    urlCallback(url);
390
-                } else {
391
-                    console.error(
392
-                        "Failed to get POPUP auth url from the focus", result);
296
+            // Not authorized to create new room
297
+            if ($(error).find('>error>not-authorized').length) {
298
+                console.warn("Unauthorized to start the conference", error);
299
+                var toDomain
300
+                    = Strophe.getDomainFromJid(error.getAttribute('to'));
301
+                if (toDomain !== this.xmppService.options.hosts.anonymousdomain) {
302
+                    //FIXME:  "is external" should come either from
303
+                    // the focus or config.js
304
+                    self.externalAuthEnabled = true;
393 305
                 }
394
-            },
395
-            function (error) {
396
-                console.error('Get POPUP auth url error', error);
306
+                self.eventEmitter.emit(
307
+                    XMPPEvents.AUTHENTICATION_REQUIRED,
308
+                    function () {
309
+                        self.allocateConferenceFocus(
310
+                            callback);
311
+                    });
312
+                return;
397 313
             }
398
-        );
399
-    },
400
-    logout: function (callback) {
401
-        var iq = $iq({to: Moderator.getFocusComponent(), type: 'set'});
402
-        var sessionId = localStorage.getItem('sessionId');
403
-        if (!sessionId) {
404
-            callback();
405
-            return;
314
+            var waitMs = self.getNextErrorTimeout();
315
+            console.error("Focus error, retry after " + waitMs, error);
316
+            // Show message
317
+            var focusComponent = self.getFocusComponent();
318
+            var retrySec = waitMs / 1000;
319
+            //FIXME:  message is duplicated ?
320
+            // Do not show in case of session invalid
321
+            // which means just a retry
322
+            if (!invalidSession) {
323
+                self.eventEmitter.emit(XMPPEvents.FOCUS_DISCONNECTED,
324
+                    focusComponent, retrySec);
325
+            }
326
+            // Reset response timeout
327
+            self.getNextTimeout(true);
328
+            window.setTimeout(
329
+                function () {
330
+                    self.allocateConferenceFocus(callback);
331
+                }, waitMs);
406 332
         }
407
-        iq.c('logout', {
408
-            xmlns: 'http://jitsi.org/protocol/focus',
409
-            'session-id': sessionId
410
-        });
411
-        connection.sendIQ(
412
-            iq,
413
-            function (result) {
414
-                var logoutUrl = $(result).find('logout').attr('logout-url');
415
-                if (logoutUrl) {
416
-                    logoutUrl = decodeURIComponent(logoutUrl);
417
-                }
418
-                console.info("Log out OK, url: " + logoutUrl, result);
419
-                localStorage.removeItem('sessionId');
420
-                callback(logoutUrl);
421
-            },
422
-            function (error) {
423
-                console.error("Logout error", error);
333
+    );
334
+};
335
+
336
+Moderator.prototype.getLoginUrl =  function (urlCallback) {
337
+    var iq = $iq({to: this.getFocusComponent(), type: 'get'});
338
+    iq.c('login-url', {
339
+        xmlns: 'http://jitsi.org/protocol/focus',
340
+        room: this.roomName,
341
+        'machine-uid': this.settings.getSettings().uid
342
+    });
343
+    this.connection.sendIQ(
344
+        iq,
345
+        function (result) {
346
+            var url = $(result).find('login-url').attr('url');
347
+            url = url = decodeURIComponent(url);
348
+            if (url) {
349
+                console.info("Got auth url: " + url);
350
+                urlCallback(url);
351
+            } else {
352
+                console.error(
353
+                    "Failed to get auth url from the focus", result);
424 354
             }
425
-        );
355
+        },
356
+        function (error) {
357
+            console.error("Get auth url error", error);
358
+        }
359
+    );
360
+};
361
+Moderator.prototype.getPopupLoginUrl =  function (urlCallback) {
362
+    var iq = $iq({to: this.getFocusComponent(), type: 'get'});
363
+    iq.c('login-url', {
364
+        xmlns: 'http://jitsi.org/protocol/focus',
365
+        room: this.roomName,
366
+        'machine-uid': this.settings.getSettings().uid,
367
+        popup: true
368
+    });
369
+    this.connection.sendIQ(
370
+        iq,
371
+        function (result) {
372
+            var url = $(result).find('login-url').attr('url');
373
+            url = url = decodeURIComponent(url);
374
+            if (url) {
375
+                console.info("Got POPUP auth url:  " + url);
376
+                urlCallback(url);
377
+            } else {
378
+                console.error(
379
+                    "Failed to get POPUP auth url from the focus", result);
380
+            }
381
+        },
382
+        function (error) {
383
+            console.error('Get POPUP auth url error', error);
384
+        }
385
+    );
386
+};
387
+
388
+Moderator.prototype.logout =  function (callback) {
389
+    var iq = $iq({to: this.getFocusComponent(), type: 'set'});
390
+    var sessionId = localStorage.getItem('sessionId');
391
+    if (!sessionId) {
392
+        callback();
393
+        return;
426 394
     }
395
+    iq.c('logout', {
396
+        xmlns: 'http://jitsi.org/protocol/focus',
397
+        'session-id': sessionId
398
+    });
399
+    this.connection.sendIQ(
400
+        iq,
401
+        function (result) {
402
+            var logoutUrl = $(result).find('logout').attr('logout-url');
403
+            if (logoutUrl) {
404
+                logoutUrl = decodeURIComponent(logoutUrl);
405
+            }
406
+            console.info("Log out OK, url: " + logoutUrl, result);
407
+            localStorage.removeItem('sessionId');
408
+            callback(logoutUrl);
409
+        },
410
+        function (error) {
411
+            console.error("Logout error", error);
412
+        }
413
+    );
427 414
 };
428 415
 
429 416
 module.exports = Moderator;

+ 46
- 15
modules/xmpp/strophe.emuc.js Näytä tiedosto

@@ -5,6 +5,7 @@
5 5
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
6 6
 var Moderator = require("./moderator");
7 7
 var RTC = require("../RTC/RTC");
8
+var EventEmitter = require("events");
8 9
 
9 10
 var parser = {
10 11
     packet2JSON: function (packet, nodes) {
@@ -46,6 +47,7 @@ var parser = {
46 47
 function ChatRoom(connection, jid, password, XMPP, eventEmitter)
47 48
 {
48 49
     this.eventEmitter = eventEmitter;
50
+    this.roomEmitter = new EventEmitter();
49 51
     this.xmpp = XMPP;
50 52
     this.connection = connection;
51 53
     this.roomjid = Strophe.getBareJidFromJid(jid);
@@ -54,11 +56,24 @@ function ChatRoom(connection, jid, password, XMPP, eventEmitter)
54 56
     console.info("Joined MUC as " + this.myroomjid);
55 57
     this.members = {};
56 58
     this.presMap = {};
59
+    this.presHandlers = {};
57 60
     this.joined = false;
58 61
     this.role = null;
59 62
     this.focusMucJid = null;
60 63
     this.bridgeIsDown = false;
64
+    this.moderator = new Moderator(this.roomjid, this.xmpp, eventEmitter);
61 65
     this.initPresenceMap();
66
+    this.readyToJoin = false;
67
+    this.joinRequested = false;
68
+    var self = this;
69
+    this.moderator.allocateConferenceFocus(function()
70
+    {
71
+        self.readyToJoin = true;
72
+        if(self.joinRequested)
73
+        {
74
+            self.join();
75
+        }
76
+    });
62 77
 }
63 78
 
64 79
 ChatRoom.prototype.initPresenceMap = function () {
@@ -84,6 +99,18 @@ ChatRoom.prototype.initPresenceMap = function () {
84 99
     });
85 100
 };
86 101
 
102
+ChatRoom.prototype.join = function (password) {
103
+    if(password)
104
+        this.password = password;
105
+    if(!this.readyToJoin)
106
+    {
107
+        this.joinRequested = true;
108
+        return;
109
+    }
110
+    this.joinRequested = false;
111
+    this.sendPresence();
112
+}
113
+
87 114
 ChatRoom.prototype.sendPresence = function () {
88 115
     if (!this.presMap['to']) {
89 116
         // Too early to send presence - not initialized
@@ -169,11 +196,11 @@ ChatRoom.prototype.onPresence = function (pres) {
169 196
     member.jid = tmp.attr('jid');
170 197
     member.isFocus = false;
171 198
     if (member.jid
172
-        && member.jid.indexOf(Moderator.getFocusUserJid() + "/") == 0) {
199
+        && member.jid.indexOf(this.moderator.getFocusUserJid() + "/") == 0) {
173 200
         member.isFocus = true;
174 201
     }
175 202
 
176
-    pres.find(">x").remove();
203
+    $(pres).find(">x").remove();
177 204
     var nodes = [];
178 205
     parser.packet2JSON(pres, nodes);
179 206
     for(var i = 0; i < nodes.length; i++)
@@ -206,7 +233,7 @@ ChatRoom.prototype.onPresence = function (pres) {
206 233
                 }
207 234
                 break;
208 235
             default :
209
-                this.processNode(node);
236
+                this.processNode(node, from);
210 237
         }
211 238
 
212 239
     }
@@ -218,7 +245,7 @@ ChatRoom.prototype.onPresence = function (pres) {
218 245
             this.role = member.role;
219 246
 
220 247
             this.eventEmitter.emit(XMPPEvents.LOCAL_ROLE_CHANGED,
221
-                member, Moderator.isModerator());
248
+                member, this.isModerator());
222 249
         }
223 250
         if (!this.joined) {
224 251
             this.joined = true;
@@ -257,8 +284,9 @@ ChatRoom.prototype.onPresence = function (pres) {
257 284
 
258 285
 };
259 286
 
260
-ChatRoom.prototype.processNode = function (node) {
261
-    this.eventEmitter.emit(XMPPEvents.PRESENCE_SETTING, node);
287
+ChatRoom.prototype.processNode = function (node, from) {
288
+    if(this.presHandlers[node.tagName])
289
+        this.presHandlers[node.tagName](node, from);
262 290
 };
263 291
 
264 292
 ChatRoom.prototype.sendMessage = function (body, nickname) {
@@ -283,9 +311,7 @@ ChatRoom.prototype.onParticipantLeft = function (jid) {
283 311
 
284 312
     this.eventEmitter.emit(XMPPEvents.MUC_MEMBER_LEFT, jid);
285 313
 
286
-    this.connection.jingle.terminateByJid(jid);
287
-
288
-    Moderator.onMucMemberLeft(jid);
314
+    this.moderator.onMucMemberLeft(jid);
289 315
 };
290 316
 
291 317
 ChatRoom.prototype.onPresenceUnavailable = function (pres, from) {
@@ -447,6 +473,14 @@ ChatRoom.prototype.removeFromPresence = function (key) {
447 473
     }
448 474
 };
449 475
 
476
+ChatRoom.prototype.addPresenceListener = function (name, handler) {
477
+    this.presHandlers[name] = handler;
478
+}
479
+
480
+ChatRoom.prototype.removePresenceListener = function (name) {
481
+    delete this.presHandlers[name];
482
+}
483
+
450 484
 ChatRoom.prototype.isModerator = function (jid) {
451 485
     return this.role === 'moderator';
452 486
 };
@@ -466,21 +500,18 @@ module.exports = function(XMPP) {
466 500
         init: function (conn) {
467 501
             this.connection = conn;
468 502
             // add handlers (just once)
469
-            this.connection.addHandler(this.onPresence.bind(this), null, 'presence', null, null);
503
+            this.connection.addHandler(this.onPresence.bind(this), null, 'presence', null, null, null, null);
470 504
             this.connection.addHandler(this.onPresenceUnavailable.bind(this), null, 'presence', 'unavailable', null);
471 505
             this.connection.addHandler(this.onPresenceError.bind(this), null, 'presence', 'error', null);
472 506
             this.connection.addHandler(this.onMessage.bind(this), null, 'message', null, null);
473 507
         },
474
-        doJoin: function (jid, password, eventEmitter) {
508
+        createRoom: function (jid, password, eventEmitter) {
475 509
             var roomJid = Strophe.getBareJidFromJid(jid);
476
-            if(this.rooms[roomJid])
477
-            {
510
+            if (this.rooms[roomJid]) {
478 511
                 console.error("You are already in the room!");
479 512
                 return;
480 513
             }
481 514
             this.rooms[roomJid] = new ChatRoom(this.connection, jid, password, XMPP, eventEmitter);
482
-
483
-            this.rooms[roomJid].sendPresence();
484 515
             return this.rooms[roomJid];
485 516
         },
486 517
         doLeave: function (jid) {

+ 1
- 52
modules/xmpp/strophe.jingle.js Näytä tiedosto

@@ -11,7 +11,6 @@ module.exports = function(XMPP, eventEmitter) {
11 11
         sessions: {},
12 12
         jid2session: {},
13 13
         ice_config: {iceServers: []},
14
-        activecall: null,
15 14
         media_constraints: {
16 15
             mandatory: {
17 16
                 'OfferToReceiveAudio': true,
@@ -108,7 +107,7 @@ module.exports = function(XMPP, eventEmitter) {
108 107
                     sess.media_constraints = this.media_constraints;
109 108
                     sess.ice_config = this.ice_config;
110 109
 
111
-                    sess.initialize(fromJid, false);
110
+                    sess.initialize(Strophe.getBareJidFromJid(fromJid), false);
112 111
                     // FIXME: setRemoteDescription should only be done when this call is to be accepted
113 112
                     sess.setOffer($(iq).find('>jingle'));
114 113
 
@@ -119,21 +118,14 @@ module.exports = function(XMPP, eventEmitter) {
119 118
                     // .sendAnswer and .accept
120 119
                     // or .sendTerminate -- not necessarily synchronous
121 120
 
122
-                    // TODO: do we check activecall == null?
123
-                    this.connection.jingle.activecall = sess;
124
-
125 121
                     eventEmitter.emit(XMPPEvents.CALL_INCOMING, sess);
126 122
 
127
-                    // TODO: check affiliation and/or role
128
-                    console.log('emuc data for', sess.peerjid,
129
-                        this.connection.emuc.members[sess.peerjid]);
130 123
                     sess.sendAnswer();
131 124
                     sess.accept();
132 125
                     break;
133 126
                 case 'session-accept':
134 127
                     sess.setAnswer($(iq).find('>jingle'));
135 128
                     sess.accept();
136
-                    $(document).trigger('callaccepted.jingle', [sess.sid]);
137 129
                     break;
138 130
                 case 'session-terminate':
139 131
                     // If this is not the focus sending the terminate, we have
@@ -188,21 +180,6 @@ module.exports = function(XMPP, eventEmitter) {
188 180
             }
189 181
             return true;
190 182
         },
191
-        initiate: function (peerjid, myjid) { // initiate a new jinglesession to peerjid
192
-            var sess = new JingleSession(myjid || this.connection.jid,
193
-                Math.random().toString(36).substr(2, 12), // random string
194
-                this.connection, XMPP, eventEmitter);
195
-            // configure session
196
-
197
-            sess.media_constraints = this.media_constraints;
198
-            sess.ice_config = this.ice_config;
199
-
200
-            sess.initialize(peerjid, true);
201
-            this.sessions[sess.sid] = sess;
202
-            this.jid2session[sess.peerjid] = sess;
203
-            sess.sendOffer();
204
-            return sess;
205
-        },
206 183
         terminate: function (sid, reason, text) { // terminate by sessionid (or all sessions)
207 184
             if (sid === null || sid === undefined) {
208 185
                 for (sid in this.sessions) {
@@ -222,34 +199,6 @@ module.exports = function(XMPP, eventEmitter) {
222 199
                 delete this.sessions[sid];
223 200
             }
224 201
         },
225
-        // Used to terminate a session when an unavailable presence is received.
226
-        terminateByJid: function (jid) {
227
-            if (this.jid2session.hasOwnProperty(jid)) {
228
-                var sess = this.jid2session[jid];
229
-                if (sess) {
230
-                    sess.terminate();
231
-                    console.log('peer went away silently', jid);
232
-                    delete this.sessions[sess.sid];
233
-                    delete this.jid2session[jid];
234
-                    $(document).trigger('callterminated.jingle',
235
-                        [sess.sid, jid], 'gone');
236
-                }
237
-            }
238
-        },
239
-        terminateRemoteByJid: function (jid, reason) {
240
-            if (this.jid2session.hasOwnProperty(jid)) {
241
-                var sess = this.jid2session[jid];
242
-                if (sess) {
243
-                    sess.sendTerminate(reason || (!sess.active()) ? 'kick' : null);
244
-                    sess.terminate();
245
-                    console.log('terminate peer with jid', sess.sid, jid);
246
-                    delete this.sessions[sess.sid];
247
-                    delete this.jid2session[jid];
248
-                    $(document).trigger('callterminated.jingle',
249
-                        [sess.sid, jid, 'kicked']);
250
-                }
251
-            }
252
-        },
253 202
         getStunAndTurnCredentials: function () {
254 203
             // get stun and turn configuration from server via xep-0215
255 204
             // uses time-limited credentials as described in

+ 20
- 59
modules/xmpp/xmpp.js Näytä tiedosto

@@ -23,7 +23,7 @@ function createConnection(bosh) {
23 23
 function initStrophePlugins(XMPP)
24 24
 {
25 25
     require("./strophe.emuc")(XMPP);
26
-//    require("./strophe.jingle")(XMPP, eventEmitter);
26
+    require("./strophe.jingle")(XMPP, XMPP.eventEmitter);
27 27
 //    require("./strophe.moderate")(XMPP, eventEmitter);
28 28
     require("./strophe.util")();
29 29
     require("./strophe.rayo")();
@@ -52,7 +52,6 @@ function initStrophePlugins(XMPP)
52 52
 //}
53 53
 
54 54
 function XMPP(options) {
55
-    this.sessionTerminated = false;
56 55
     this.eventEmitter = new EventEmitter();
57 56
     this.connection = null;
58 57
     this.disconnectInProgress = false;
@@ -61,9 +60,8 @@ function XMPP(options) {
61 60
     this.options = options;
62 61
     initStrophePlugins(this);
63 62
 //    registerListeners();
64
-    Moderator.init(this, this.eventEmitter);
63
+
65 64
     this.connection = createConnection(options.bosh);
66
-    Moderator.setConnection(this.connection);
67 65
 }
68 66
 
69 67
 
@@ -118,7 +116,7 @@ XMPP.prototype._connect = function (jid, password) {
118 116
             if (self.connection && self.connection.connected &&
119 117
                 Strophe.getResourceFromJid(self.connection.jid)) {
120 118
                 // .connected is true while connecting?
121
-                self.connection.send($pres());
119
+//                self.connection.send($pres());
122 120
                 self.eventEmitter.emit(JitsiConnectionEvents.CONNECTION_ESTABLISHED,
123 121
                     Strophe.getResourceFromJid(self.connection.jid));
124 122
             }
@@ -167,8 +165,8 @@ XMPP.prototype.connect = function (jid, password) {
167 165
     return this._connect(jid, password);
168 166
 };
169 167
 
170
-XMPP.prototype.joinRoom = function(roomName, useNicks, nick) {
171
-    var roomjid = roomName  + '@' + Strophe.getDomainFromJid(this.connection.jid);
168
+XMPP.prototype.createRoom = function (roomName, useNicks, nick) {
169
+    var roomjid = roomName  + '@' + this.options.hosts.muc;
172 170
 
173 171
     if (useNicks) {
174 172
         if (nick) {
@@ -184,70 +182,37 @@ XMPP.prototype.joinRoom = function(roomName, useNicks, nick) {
184 182
 
185 183
         roomjid += '/' + tmpJid;
186 184
     }
187
-    return this.connection.emuc.doJoin(roomjid, null, this.eventEmitter);
185
+
186
+    return this.connection.emuc.createRoom(roomjid, null, this.eventEmitter);
187
+}
188
+
189
+XMPP.prototype.addListener = function(type, listener) {
190
+    this.eventEmitter.on(type, listener);
188 191
 };
189 192
 
193
+XMPP.prototype.removeListener = function (type, listener) {
194
+    this.eventEmitter.removeListener(type, listener);
195
+};
190 196
 
191
-XMPP.prototype.disposeConference = function (onUnload) {
192
-    var handler = this.connection.jingle.activecall;
197
+XMPP.prototype.leaveRoom = function (jid) {
198
+    var handler = this.connection.jingle.jid2session[jid];
193 199
     if (handler && handler.peerconnection) {
194 200
         // FIXME: probably removing streams is not required and close() should
195 201
         // be enough
196 202
         if (RTC.localAudio) {
197 203
             handler.peerconnection.removeStream(
198
-                RTC.localAudio.getOriginalStream(), onUnload);
204
+                RTC.localAudio.getOriginalStream(), true);
199 205
         }
200 206
         if (RTC.localVideo) {
201 207
             handler.peerconnection.removeStream(
202
-                RTC.localVideo.getOriginalStream(), onUnload);
208
+                RTC.localVideo.getOriginalStream(), true);
203 209
         }
204 210
         handler.peerconnection.close();
205 211
     }
206
-    this.eventEmitter.emit(XMPPEvents.DISPOSE_CONFERENCE, onUnload);
207
-    this.connection.jingle.activecall = null;
208
-    if (!onUnload) {
209
-        this.sessionTerminated = true;
210
-        this.connection.emuc.doLeave();
211
-    }
212
-};
213
-
214
-XMPP.prototype.addListener = function(type, listener) {
215
-    this.eventEmitter.on(type, listener);
216
-};
217
-
218
-XMPP.prototype.removeListener = function (type, listener) {
219
-    this.eventEmitter.removeListener(type, listener);
220
-};
221
-
222
-XMPP.prototype.leaveRoom = function (jid) {
212
+    this.eventEmitter.emit(XMPPEvents.DISPOSE_CONFERENCE);
223 213
     this.connection.emuc.doLeave(jid);
224 214
 };
225 215
 
226
-
227
-XMPP.prototype.allocateConferenceFocus = function(roomName, callback) {
228
-    Moderator.allocateConferenceFocus(roomName, callback);
229
-};
230
-
231
-XMPP.prototype.getLoginUrl = function (roomName, callback) {
232
-    Moderator.getLoginUrl(roomName, callback);
233
-}
234
-
235
-XMPP.prototype.getPopupLoginUrl = function (roomName, callback) {
236
-    Moderator.getPopupLoginUrl(roomName, callback);
237
-};
238
-
239
-XMPP.prototype.isModerator = function () {
240
-    return Moderator.isModerator();
241
-};
242
-
243
-XMPP.prototype.isSipGatewayEnabled = function () {
244
-    return Moderator.isSipGatewayEnabled();
245
-}
246
-
247
-XMPP.prototype.isExternalAuthEnabled = function () {
248
-    return Moderator.isExternalAuthEnabled();
249
-};
250
-
251 216
 XMPP.prototype.isConferenceInProgress = function () {
252 217
     return this.connection && this.connection.jingle.activecall &&
253 218
         this.connection.jingle.activecall.peerconnection;
@@ -376,10 +341,6 @@ XMPP.prototype.eject = function (jid) {
376 341
     this.connection.moderate.eject(jid);
377 342
 };
378 343
 
379
-XMPP.prototype.logout = function (callback) {
380
-    Moderator.logout(callback);
381
-};
382
-
383 344
 XMPP.prototype.getJidFromSSRC = function (ssrc) {
384 345
     if (!this.isConferenceInProgress())
385 346
         return null;
@@ -396,7 +357,7 @@ XMPP.prototype.removeStream = function (stream) {
396 357
     this.connection.jingle.activecall.peerconnection.removeStream(stream);
397 358
 };
398 359
 
399
-XMPP.prototype.disconnect = function (callback) {
360
+XMPP.prototype.disconnect = function () {
400 361
     if (this.disconnectInProgress || !this.connection || !this.connection.connected)
401 362
     {
402 363
         this.eventEmitter.emit(JitsiConnectionEvents.WRONG_STATE);

+ 2
- 1
service/xmpp/XMPPEvents.js Näytä tiedosto

@@ -49,6 +49,7 @@ var XMPPEvents = {
49 49
     ROOM_JOIN_ERROR: 'xmpp.room_join_error',
50 50
     ROOM_CONNECT_ERROR: 'xmpp.room_connect_error',
51 51
     // xmpp is connected and obtained user media
52
-    READY_TO_JOIN: 'xmpp.ready_to_join'
52
+    READY_TO_JOIN: 'xmpp.ready_to_join',
53
+    FOCUS_LEFT: "xmpp.focus_left"
53 54
 };
54 55
 module.exports = XMPPEvents;

Loading…
Peruuta
Tallenna