瀏覽代碼

ref(module/xmpp): ES6 for modules/xmpp/xmpp.js and it's related files

master
hristoterezov 8 年之前
父節點
當前提交
9781a0d63c

+ 1
- 1
JitsiConnection.js 查看文件

@@ -1,7 +1,7 @@
1 1
 var JitsiConference = require("./JitsiConference");
2
-var XMPP = require("./modules/xmpp/xmpp");
3 2
 import * as JitsiConnectionErrors from "./JitsiConnectionErrors";
4 3
 import * as JitsiConnectionEvents from "./JitsiConnectionEvents";
4
+import XMPP from "./modules/xmpp/xmpp";
5 5
 var Statistics = require("./modules/statistics/statistics");
6 6
 
7 7
 /**

+ 2
- 1
modules/xmpp/ChatRoom.js 查看文件

@@ -1,6 +1,7 @@
1 1
 /* global Strophe, $, $pres, $iq, $msg */
2 2
 /* jshint -W101,-W069 */
3
-var logger = require("jitsi-meet-logger").getLogger(__filename);
3
+import {getLogger} from "jitsi-meet-logger";
4
+const logger = getLogger(__filename);
4 5
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
5 6
 var MediaType = require("../../service/RTC/MediaType");
6 7
 var Moderator = require("./moderator");

+ 11
- 0
modules/xmpp/ConnectionPlugin.js 查看文件

@@ -0,0 +1,11 @@
1
+/**
2
+ * Base class for strophe connection plugins.
3
+ */
4
+export default class ConnectionPlugin {
5
+    constructor() {
6
+        this.connection = null;
7
+    }
8
+    init (connection) {
9
+        this.connection = connection;
10
+    }
11
+}

+ 2
- 1
modules/xmpp/JingleSession.js 查看文件

@@ -3,7 +3,8 @@
3 3
  * have different implementations depending on the underlying interface used
4 4
  * (i.e. WebRTC and ORTC) and here we hold the code common to all of them.
5 5
  */
6
-var logger = require("jitsi-meet-logger").getLogger(__filename);
6
+import {getLogger} from "jitsi-meet-logger";
7
+const logger = getLogger(__filename);
7 8
 
8 9
 function JingleSession(me, sid, peerjid, connection,
9 10
                        media_constraints, ice_config, service, eventEmitter) {

+ 2
- 2
modules/xmpp/JingleSessionPC.js 查看文件

@@ -1,6 +1,6 @@
1 1
 /* jshint -W117 */
2
-
3
-var logger = require("jitsi-meet-logger").getLogger(__filename);
2
+import {getLogger} from "jitsi-meet-logger";
3
+const logger = getLogger(__filename);
4 4
 var JingleSession = require("./JingleSession");
5 5
 var TraceablePeerConnection = require("./TraceablePeerConnection");
6 6
 var MediaType = require("../../service/RTC/MediaType");

+ 2
- 2
modules/xmpp/SDP.js 查看文件

@@ -1,6 +1,6 @@
1 1
 /* jshint -W117 */
2
-
3
-var logger = require("jitsi-meet-logger").getLogger(__filename);
2
+import {getLogger} from "jitsi-meet-logger";
3
+const logger = getLogger(__filename);
4 4
 var SDPUtil = require("./SDPUtil");
5 5
 
6 6
 // SDP STUFF

+ 2
- 1
modules/xmpp/SDPUtil.js 查看文件

@@ -1,4 +1,5 @@
1
-var logger = require("jitsi-meet-logger").getLogger(__filename);
1
+import {getLogger} from "jitsi-meet-logger";
2
+const logger = getLogger(__filename);
2 3
 var RTCBrowserType = require("../RTC/RTCBrowserType");
3 4
 
4 5
 

+ 2
- 1
modules/xmpp/TraceablePeerConnection.js 查看文件

@@ -1,6 +1,7 @@
1 1
 /* global $ */
2
+import {getLogger} from "jitsi-meet-logger";
3
+const logger = getLogger(__filename);
2 4
 var RTC = require('../RTC/RTC');
3
-var logger = require("jitsi-meet-logger").getLogger(__filename);
4 5
 var RTCBrowserType = require("../RTC/RTCBrowserType.js");
5 6
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
6 7
 var transform = require('sdp-transform');

+ 2
- 1
modules/xmpp/recording.js 查看文件

@@ -1,10 +1,11 @@
1 1
 /* global $, $iq, config, connection, focusMucJid, messageHandler,
2 2
    Toolbar, Util, Promise */
3
+import {getLogger} from "jitsi-meet-logger";
4
+const logger = getLogger(__filename);
3 5
 var XMPPEvents = require("../../service/xmpp/XMPPEvents");
4 6
 var JitsiRecorderErrors = require("../../JitsiRecorderErrors");
5 7
 var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
6 8
 
7
-var logger = require("jitsi-meet-logger").getLogger(__filename);
8 9
 
9 10
 function Recording(type, eventEmitter, connection, focusMucJid, jirecon,
10 11
     roomjid) {

+ 112
- 98
modules/xmpp/strophe.emuc.js 查看文件

@@ -2,109 +2,123 @@
2 2
 /* a simple MUC connection plugin
3 3
  * can only handle a single MUC room
4 4
  */
5
+import {getLogger} from "jitsi-meet-logger";
6
+const logger = getLogger(__filename);
7
+import ChatRoom from "./ChatRoom";
8
+import ConnectionPlugin from "./ConnectionPlugin";
5 9
 
6
-var logger = require("jitsi-meet-logger").getLogger(__filename);
7
-var ChatRoom = require("./ChatRoom");
8
-
9
-module.exports = function(XMPP) {
10
-    Strophe.addConnectionPlugin('emuc', {
11
-        connection: null,
12
-        rooms: {},//map with the rooms
13
-        init: function (conn) {
14
-            this.connection = conn;
15
-            // add handlers (just once)
16
-            this.connection.addHandler(this.onPresence.bind(this), null,
17
-                'presence', null, null, null, null);
18
-            this.connection.addHandler(this.onPresenceUnavailable.bind(this),
19
-                null, 'presence', 'unavailable', null);
20
-            this.connection.addHandler(this.onPresenceError.bind(this), null,
21
-                'presence', 'error', null);
22
-            this.connection.addHandler(this.onMessage.bind(this), null,
23
-                'message', null, null);
24
-            this.connection.addHandler(this.onMute.bind(this),
25
-                'http://jitsi.org/jitmeet/audio', 'iq', 'set',null,null);
26
-        },
27
-        createRoom: function (jid, password, options, settings) {
28
-            var roomJid = Strophe.getBareJidFromJid(jid);
29
-            if (this.rooms[roomJid]) {
30
-                var errmsg = "You are already in the room!";
31
-                logger.error(errmsg);
32
-                throw new Error(errmsg);
33
-                return;
34
-            }
35
-            this.rooms[roomJid] = new ChatRoom(this.connection, jid,
36
-                password, XMPP, options, settings);
37
-            return this.rooms[roomJid];
38
-        },
39
-        doLeave: function (jid) {
40
-            delete this.rooms[jid];
41
-        },
42
-        onPresence: function (pres) {
43
-            var from = pres.getAttribute('from');
44
-
45
-            // What is this for? A workaround for something?
46
-            if (pres.getAttribute('type')) {
47
-                return true;
48
-            }
49
-
50
-            var room = this.rooms[Strophe.getBareJidFromJid(from)];
51
-            if(!room)
52
-                return;
53
-
54
-            // Parse status.
55
-            if ($(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]>status[code="201"]').length) {
56
-                room.createNonAnonymousRoom();
57
-            }
58
-
59
-            room.onPresence(pres);
10
+class MucConnectionPlugin extends ConnectionPlugin {
11
+    constructor(xmpp) {
12
+        super();
13
+        this.xmpp = xmpp;
14
+        this.rooms = {};
15
+    }
60 16
 
61
-            return true;
62
-        },
63
-        onPresenceUnavailable: function (pres) {
64
-            var from = pres.getAttribute('from');
65
-            var room = this.rooms[Strophe.getBareJidFromJid(from)];
66
-            if(!room)
67
-                return;
68
-
69
-            room.onPresenceUnavailable(pres, from);
70
-            return true;
71
-        },
72
-        onPresenceError: function (pres) {
73
-            var from = pres.getAttribute('from');
74
-            var room = this.rooms[Strophe.getBareJidFromJid(from)];
75
-            if(!room)
76
-                return;
77
-
78
-            room.onPresenceError(pres, from);
79
-            return true;
80
-        },
81
-        onMessage: function (msg) {
82
-            // FIXME: this is a hack. but jingle on muc makes nickchanges hard
83
-            var from = msg.getAttribute('from');
84
-            var room = this.rooms[Strophe.getBareJidFromJid(from)];
85
-            if(!room)
86
-                return;
87
-
88
-            room.onMessage(msg, from);
89
-            return true;
90
-        },
17
+    init (connection) {
18
+        super.init(connection);
19
+        // add handlers (just once)
20
+        this.connection.addHandler(this.onPresence.bind(this), null,
21
+            'presence', null, null, null, null);
22
+        this.connection.addHandler(this.onPresenceUnavailable.bind(this),
23
+            null, 'presence', 'unavailable', null);
24
+        this.connection.addHandler(this.onPresenceError.bind(this), null,
25
+            'presence', 'error', null);
26
+        this.connection.addHandler(this.onMessage.bind(this), null,
27
+            'message', null, null);
28
+        this.connection.addHandler(this.onMute.bind(this),
29
+            'http://jitsi.org/jitmeet/audio', 'iq', 'set',null,null);
30
+    }
91 31
 
92
-        setJingleSession: function (from, session) {
93
-            var room = this.rooms[Strophe.getBareJidFromJid(from)];
94
-            if(!room)
95
-                return;
32
+    createRoom (jid, password, options, settings) {
33
+        const roomJid = Strophe.getBareJidFromJid(jid);
34
+        if (this.rooms[roomJid]) {
35
+            const errmsg = "You are already in the room!";
36
+            logger.error(errmsg);
37
+            throw new Error(errmsg);
38
+            return;
39
+        }
40
+        this.rooms[roomJid] = new ChatRoom(this.connection, jid,
41
+            password, this.xmpp, options, settings);
42
+        return this.rooms[roomJid];
43
+    }
96 44
 
97
-            room.setJingleSession(session);
98
-        },
45
+    doLeave (jid) {
46
+        delete this.rooms[jid];
47
+    }
99 48
 
100
-        onMute: function(iq) {
101
-            var from = iq.getAttribute('from');
102
-            var room = this.rooms[Strophe.getBareJidFromJid(from)];
103
-            if(!room)
104
-                return;
49
+    onPresence (pres) {
50
+        const from = pres.getAttribute('from');
105 51
 
106
-            room.onMute(iq);
52
+        // What is this for? A workaround for something?
53
+        if (pres.getAttribute('type')) {
107 54
             return true;
108 55
         }
109
-    });
110
-};
56
+
57
+        const room = this.rooms[Strophe.getBareJidFromJid(from)];
58
+        if(!room)
59
+            return;
60
+
61
+        // Parse status.
62
+        if ($(pres).find('>x[xmlns="http://jabber.org/protocol/muc#user"]' +
63
+            '>status[code="201"]').length) {
64
+            room.createNonAnonymousRoom();
65
+        }
66
+
67
+        room.onPresence(pres);
68
+
69
+        return true;
70
+    }
71
+
72
+    onPresenceUnavailable (pres) {
73
+        const from = pres.getAttribute('from');
74
+        const room = this.rooms[Strophe.getBareJidFromJid(from)];
75
+        if(!room)
76
+            return;
77
+
78
+        room.onPresenceUnavailable(pres, from);
79
+        return true;
80
+    }
81
+
82
+    onPresenceError (pres) {
83
+        const from = pres.getAttribute('from');
84
+        const room = this.rooms[Strophe.getBareJidFromJid(from)];
85
+        if(!room)
86
+            return;
87
+
88
+        room.onPresenceError(pres, from);
89
+        return true;
90
+    }
91
+
92
+    onMessage (msg) {
93
+        // FIXME: this is a hack. but jingle on muc makes nickchanges hard
94
+        const from = msg.getAttribute('from');
95
+        const room = this.rooms[Strophe.getBareJidFromJid(from)];
96
+        if(!room)
97
+            return;
98
+
99
+        room.onMessage(msg, from);
100
+        return true;
101
+    }
102
+
103
+    setJingleSession (from, session) {
104
+        const room = this.rooms[Strophe.getBareJidFromJid(from)];
105
+        if(!room)
106
+            return;
107
+
108
+        room.setJingleSession(session);
109
+    }
110
+
111
+    onMute(iq) {
112
+        const from = iq.getAttribute('from');
113
+        const room = this.rooms[Strophe.getBareJidFromJid(from)];
114
+        if(!room)
115
+            return;
116
+
117
+        room.onMute(iq);
118
+        return true;
119
+    }
120
+}
121
+
122
+export default function(XMPP) {
123
+    Strophe.addConnectionPlugin('emuc', new MucConnectionPlugin(XMPP));
124
+}

+ 250
- 229
modules/xmpp/strophe.jingle.js 查看文件

@@ -1,252 +1,273 @@
1 1
 /* jshint -W117 */
2
+import {getLogger} from "jitsi-meet-logger";
3
+const logger = getLogger(__filename);
4
+import JingleSession from "./JingleSessionPC";
5
+import XMPPEvents from "../../service/xmpp/XMPPEvents";
6
+import RTCBrowserType from "../RTC/RTCBrowserType";
7
+import GlobalOnErrorHandler from "../util/GlobalOnErrorHandler";
8
+import Statistics from "../statistics/statistics";
9
+import ConnectionPlugin from "./ConnectionPlugin";
2 10
 
3
-
4
-var logger = require("jitsi-meet-logger").getLogger(__filename);
5
-var JingleSession = require("./JingleSessionPC");
6
-var XMPPEvents = require("../../service/xmpp/XMPPEvents");
7
-var RTCBrowserType = require("../RTC/RTCBrowserType");
8
-var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
9
-var Statistics = require("../statistics/statistics");
10
-
11
-module.exports = function(XMPP, eventEmitter) {
12
-    Strophe.addConnectionPlugin('jingle', {
13
-        connection: null,
14
-        sessions: {},
15
-        ice_config: {iceServers: []},
16
-        media_constraints: {
11
+class JingleConnectionPlugin extends ConnectionPlugin {
12
+    constructor(xmpp, eventEmitter) {
13
+        super();
14
+        this.xmpp = xmpp;
15
+        this.eventEmitter = eventEmitter;
16
+        this.sessions = {};
17
+        this.ice_config = {iceServers: []};
18
+        this.media_constraints = {
17 19
             mandatory: {
18 20
                 'OfferToReceiveAudio': true,
19 21
                 'OfferToReceiveVideo': true
20 22
             }
21 23
             // MozDontOfferDataChannel: true when this is firefox
22
-        },
23
-        init: function (conn) {
24
-            this.connection = conn;
25
-            this.connection.addHandler(this.onJingle.bind(this), 'urn:xmpp:jingle:1', 'iq', 'set', null, null);
26
-        },
27
-        onJingle: function (iq) {
28
-            var sid = $(iq).find('jingle').attr('sid');
29
-            var action = $(iq).find('jingle').attr('action');
30
-            var fromJid = iq.getAttribute('from');
31
-            // send ack first
32
-            var ack = $iq({type: 'result',
33
-                to: fromJid,
34
-                id: iq.getAttribute('id')
35
-            });
36
-            logger.log('on jingle ' + action + ' from ' + fromJid, iq);
37
-            var sess = this.sessions[sid];
38
-            if ('session-initiate' != action) {
39
-                if (!sess) {
40
-                    ack.attrs({ type: 'error' });
41
-                    ack.c('error', {type: 'cancel'})
42
-                        .c('item-not-found', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up()
43
-                        .c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});
44
-                    logger.warn('invalid session id', iq);
45
-                    this.connection.send(ack);
46
-                    return true;
47
-                }
48
-                // local jid is not checked
49
-                if (fromJid != sess.peerjid) {
50
-                    logger.warn(
51
-                        'jid mismatch for session id', sid, sess.peerjid, iq);
52
-                    ack.attrs({ type: 'error' });
53
-                    ack.c('error', {type: 'cancel'})
54
-                        .c('item-not-found', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up()
55
-                        .c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});
56
-                    this.connection.send(ack);
57
-                    return true;
58
-                }
59
-            } else if (sess !== undefined) {
60
-                // existing session with same session id
61
-                // this might be out-of-order if the sess.peerjid is the same as from
24
+        };
25
+    }
26
+
27
+    init (connection) {
28
+        super.init(connection);
29
+        this.connection.addHandler(this.onJingle.bind(this),
30
+            'urn:xmpp:jingle:1', 'iq', 'set', null, null);
31
+    }
32
+
33
+    onJingle (iq) {
34
+        const sid = $(iq).find('jingle').attr('sid');
35
+        const action = $(iq).find('jingle').attr('action');
36
+        const fromJid = iq.getAttribute('from');
37
+        // send ack first
38
+        const ack = $iq({type: 'result',
39
+            to: fromJid,
40
+            id: iq.getAttribute('id')
41
+        });
42
+        logger.log('on jingle ' + action + ' from ' + fromJid, iq);
43
+        let sess = this.sessions[sid];
44
+        if ('session-initiate' != action) {
45
+            if (!sess) {
62 46
                 ack.attrs({ type: 'error' });
63 47
                 ack.c('error', {type: 'cancel'})
64
-                    .c('service-unavailable', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up();
65
-                logger.warn('duplicate session id', sid, iq);
48
+                    .c('item-not-found', {
49
+                        xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up()
50
+                    .c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});
51
+                logger.warn('invalid session id', iq);
66 52
                 this.connection.send(ack);
67 53
                 return true;
68 54
             }
69
-            // see http://xmpp.org/extensions/xep-0166.html#concepts-session
70
-            switch (action) {
71
-                case 'session-initiate':
72
-                    var now = window.performance.now();
73
-                    logger.log("(TIME) received session-initiate:\t", now);
74
-                    var startMuted = $(iq).find('jingle>startmuted');
75
-                    if (startMuted && startMuted.length > 0) {
76
-                        var audioMuted = startMuted.attr("audio");
77
-                        var videoMuted = startMuted.attr("video");
78
-                        eventEmitter.emit(XMPPEvents.START_MUTED_FROM_FOCUS,
79
-                                audioMuted === "true", videoMuted === "true");
80
-                    }
81
-                    sess = new JingleSession(
82
-                            $(iq).attr('to'), $(iq).find('jingle').attr('sid'),
83
-                            fromJid,
84
-                            this.connection,
85
-                            this.media_constraints,
86
-                            this.ice_config, XMPP);
87
-
88
-                    this.sessions[sess.sid] = sess;
55
+            // local jid is not checked
56
+            if (fromJid != sess.peerjid) {
57
+                logger.warn(
58
+                    'jid mismatch for session id', sid, sess.peerjid, iq);
59
+                ack.attrs({ type: 'error' });
60
+                ack.c('error', {type: 'cancel'})
61
+                    .c('item-not-found', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up()
62
+                    .c('unknown-session', {xmlns: 'urn:xmpp:jingle:errors:1'});
63
+                this.connection.send(ack);
64
+                return true;
65
+            }
66
+        } else if (sess !== undefined) {
67
+            // existing session with same session id
68
+            // this might be out-of-order if the sess.peerjid is the same as from
69
+            ack.attrs({ type: 'error' });
70
+            ack.c('error', {type: 'cancel'})
71
+                .c('service-unavailable', {xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas'}).up();
72
+            logger.warn('duplicate session id', sid, iq);
73
+            this.connection.send(ack);
74
+            return true;
75
+        }
76
+        const now = window.performance.now();
77
+        // see http://xmpp.org/extensions/xep-0166.html#concepts-session
78
+        switch (action) {
79
+            case 'session-initiate':
80
+                logger.log("(TIME) received session-initiate:\t", now);
81
+                const startMuted = $(iq).find('jingle>startmuted');
82
+                if (startMuted && startMuted.length > 0) {
83
+                    const audioMuted = startMuted.attr("audio");
84
+                    const videoMuted = startMuted.attr("video");
85
+                    this.eventEmitter.emit(XMPPEvents.START_MUTED_FROM_FOCUS,
86
+                            audioMuted === "true", videoMuted === "true");
87
+                }
88
+                sess = new JingleSession(
89
+                        $(iq).attr('to'), $(iq).find('jingle').attr('sid'),
90
+                        fromJid,
91
+                        this.connection,
92
+                        this.media_constraints,
93
+                        this.ice_config, this.xmpp);
89 94
 
90
-                    var jingleOffer = $(iq).find('>jingle');
91
-                    // FIXME there's no nice way with event to get the reason
92
-                    // why the call was rejected
93
-                    eventEmitter.emit(XMPPEvents.CALL_INCOMING, sess, jingleOffer, now);
94
-                    if (!sess.active())
95
-                    {
96
-                        // Call not accepted
97
-                        ack.attrs({ type: 'error' });
98
-                        ack.c('error', {type: 'cancel'})
99
-                           .c('bad-request',
100
-                            { xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas' })
101
-                            .up();
102
-                        this.terminate(sess.sid);
103
-                    }
104
-                    Statistics.analytics.sendEvent(
105
-                        'xmpp.session-initiate', now);
106
-                    break;
107
-                case 'session-terminate':
108
-                    logger.log('terminating...', sess.sid);
109
-                    var reasonCondition = null;
110
-                    var reasonText = null;
111
-                    if ($(iq).find('>jingle>reason').length) {
112
-                        reasonCondition
113
-                            = $(iq).find('>jingle>reason>:first')[0].tagName;
114
-                        reasonText = $(iq).find('>jingle>reason>text').text();
115
-                    }
116
-                    this.terminate(sess.sid, reasonCondition, reasonText);
117
-                    eventEmitter.emit(XMPPEvents.CALL_ENDED,
118
-                        sess, reasonCondition, reasonText);
119
-                    break;
120
-                case 'transport-replace':
121
-                    var now = window.performance.now();
122
-                    logger.info("(TIME) Start transport replace", now);
123
-                    Statistics.analytics.sendEvent(
124
-                        'xmpp.transport-replace.start', now);
95
+                this.sessions[sess.sid] = sess;
125 96
 
126
-                    sess.replaceTransport($(iq).find('>jingle'),
127
-                        function () {
128
-                            var now = window.performance.now();
129
-                            logger.info(
130
-                                "(TIME) Transport replace success!", now);
131
-                            Statistics.analytics.sendEvent(
132
-                                'xmpp.transport-replace.success', now);
133
-                        },
134
-                        function(error) {
135
-                            GlobalOnErrorHandler.callErrorHandler(error);
136
-                            logger.error('Transport replace failed', error);
137
-                            sess.sendTransportReject();
138
-                        });
139
-                    break;
140
-                case 'addsource': // FIXME: proprietary, un-jingleish
141
-                case 'source-add': // FIXME: proprietary
142
-                    sess.addSource($(iq).find('>jingle>content'));
143
-                    break;
144
-                case 'removesource': // FIXME: proprietary, un-jingleish
145
-                case 'source-remove': // FIXME: proprietary
146
-                    sess.removeSource($(iq).find('>jingle>content'));
147
-                    break;
148
-                default:
149
-                    logger.warn('jingle action not implemented', action);
97
+                let jingleOffer = $(iq).find('>jingle');
98
+                // FIXME there's no nice way with event to get the reason
99
+                // why the call was rejected
100
+                this.eventEmitter.emit(XMPPEvents.CALL_INCOMING,
101
+                    sess, jingleOffer, now);
102
+                if (!sess.active())
103
+                {
104
+                    // Call not accepted
150 105
                     ack.attrs({ type: 'error' });
151 106
                     ack.c('error', {type: 'cancel'})
152
-                        .c('bad-request',
153
-                            { xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas' })
107
+                       .c('bad-request',
108
+                        { xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas' })
154 109
                         .up();
155
-                    break;
156
-            }
157
-            this.connection.send(ack);
158
-            return true;
159
-        },
160
-        terminate: function (sid, reasonCondition, reasonText) {
161
-            if (this.sessions.hasOwnProperty(sid)) {
162
-                if (this.sessions[sid].state != 'ended') {
163
-                    this.sessions[sid].onTerminated(reasonCondition, reasonText);
110
+                    this.terminate(sess.sid);
111
+                }
112
+                Statistics.analytics.sendEvent(
113
+                    'xmpp.session-initiate', now);
114
+                break;
115
+            case 'session-terminate':
116
+                logger.log('terminating...', sess.sid);
117
+                let reasonCondition = null;
118
+                let reasonText = null;
119
+                if ($(iq).find('>jingle>reason').length) {
120
+                    reasonCondition
121
+                        = $(iq).find('>jingle>reason>:first')[0].tagName;
122
+                    reasonText = $(iq).find('>jingle>reason>text').text();
164 123
                 }
165
-                delete this.sessions[sid];
124
+                this.terminate(sess.sid, reasonCondition, reasonText);
125
+                this.eventEmitter.emit(XMPPEvents.CALL_ENDED,
126
+                    sess, reasonCondition, reasonText);
127
+                break;
128
+            case 'transport-replace':
129
+                logger.info("(TIME) Start transport replace", now);
130
+                Statistics.analytics.sendEvent(
131
+                    'xmpp.transport-replace.start', now);
132
+
133
+                sess.replaceTransport($(iq).find('>jingle'), () => {
134
+                    const successTime = window.performance.now();
135
+                    logger.info(
136
+                        "(TIME) Transport replace success!", successTime);
137
+                    Statistics.analytics.sendEvent(
138
+                        'xmpp.transport-replace.success', successTime);
139
+                }, (error) => {
140
+                    GlobalOnErrorHandler.callErrorHandler(error);
141
+                    logger.error('Transport replace failed', error);
142
+                    sess.sendTransportReject();
143
+                });
144
+                break;
145
+            case 'addsource': // FIXME: proprietary, un-jingleish
146
+            case 'source-add': // FIXME: proprietary
147
+                sess.addSource($(iq).find('>jingle>content'));
148
+                break;
149
+            case 'removesource': // FIXME: proprietary, un-jingleish
150
+            case 'source-remove': // FIXME: proprietary
151
+                sess.removeSource($(iq).find('>jingle>content'));
152
+                break;
153
+            default:
154
+                logger.warn('jingle action not implemented', action);
155
+                ack.attrs({ type: 'error' });
156
+                ack.c('error', {type: 'cancel'})
157
+                    .c('bad-request',
158
+                        { xmlns: 'urn:ietf:params:xml:ns:xmpp-stanzas' })
159
+                    .up();
160
+                break;
161
+        }
162
+        this.connection.send(ack);
163
+        return true;
164
+    }
165
+
166
+    terminate (sid, reasonCondition, reasonText) {
167
+        if (this.sessions.hasOwnProperty(sid)) {
168
+            if (this.sessions[sid].state != 'ended') {
169
+                this.sessions[sid].onTerminated(reasonCondition, reasonText);
166 170
             }
167
-        },
168
-        getStunAndTurnCredentials: function () {
169
-            // get stun and turn configuration from server via xep-0215
170
-            // uses time-limited credentials as described in
171
-            // http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
172
-            //
173
-            // see https://code.google.com/p/prosody-modules/source/browse/mod_turncredentials/mod_turncredentials.lua
174
-            // for a prosody module which implements this
175
-            //
176
-            // currently, this doesn't work with updateIce and therefore credentials with a long
177
-            // validity have to be fetched before creating the peerconnection
178
-            // TODO: implement refresh via updateIce as described in
179
-            //      https://code.google.com/p/webrtc/issues/detail?id=1650
180
-            var self = this;
181
-            this.connection.sendIQ(
182
-                $iq({type: 'get', to: this.connection.domain})
183
-                    .c('services', {xmlns: 'urn:xmpp:extdisco:1'}).c('service', {host: 'turn.' + this.connection.domain}),
184
-                function (res) {
185
-                    var iceservers = [];
186
-                    $(res).find('>services>service').each(function (idx, el) {
187
-                        el = $(el);
188
-                        var dict = {};
189
-                        var type = el.attr('type');
190
-                        switch (type) {
191
-                            case 'stun':
192
-                                dict.url = 'stun:' + el.attr('host');
193
-                                if (el.attr('port')) {
194
-                                    dict.url += ':' + el.attr('port');
195
-                                }
196
-                                iceservers.push(dict);
197
-                                break;
198
-                            case 'turn':
199
-                            case 'turns':
200
-                                dict.url = type + ':';
201
-                                if (el.attr('username')) { // https://code.google.com/p/webrtc/issues/detail?id=1508
202
-                                    if (navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./) && parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10) < 28) {
203
-                                        dict.url += el.attr('username') + '@';
204
-                                    } else {
205
-                                        dict.username = el.attr('username'); // only works in M28
206
-                                    }
207
-                                }
208
-                                dict.url += el.attr('host');
209
-                                if (el.attr('port') && el.attr('port') != '3478') {
210
-                                    dict.url += ':' + el.attr('port');
211
-                                }
212
-                                if (el.attr('transport') && el.attr('transport') != 'udp') {
213
-                                    dict.url += '?transport=' + el.attr('transport');
214
-                                }
215
-                                if (el.attr('password')) {
216
-                                    dict.credential = el.attr('password');
171
+            delete this.sessions[sid];
172
+        }
173
+    }
174
+
175
+    getStunAndTurnCredentials () {
176
+        // get stun and turn configuration from server via xep-0215
177
+        // uses time-limited credentials as described in
178
+        // http://tools.ietf.org/html/draft-uberti-behave-turn-rest-00
179
+        //
180
+        // see https://code.google.com/p/prosody-modules/source/browse/mod_turncredentials/mod_turncredentials.lua
181
+        // for a prosody module which implements this
182
+        //
183
+        // currently, this doesn't work with updateIce and therefore credentials with a long
184
+        // validity have to be fetched before creating the peerconnection
185
+        // TODO: implement refresh via updateIce as described in
186
+        //      https://code.google.com/p/webrtc/issues/detail?id=1650
187
+        this.connection.sendIQ(
188
+            $iq({type: 'get', to: this.connection.domain})
189
+                .c('services', {xmlns: 'urn:xmpp:extdisco:1'})
190
+                .c('service', {host: 'turn.' + this.connection.domain}),
191
+            (res) => {
192
+                let iceservers = [];
193
+                $(res).find('>services>service').each((idx, el) => {
194
+                    el = $(el);
195
+                    let dict = {};
196
+                    const type = el.attr('type');
197
+                    switch (type) {
198
+                        case 'stun':
199
+                            dict.url = 'stun:' + el.attr('host');
200
+                            if (el.attr('port')) {
201
+                                dict.url += ':' + el.attr('port');
202
+                            }
203
+                            iceservers.push(dict);
204
+                            break;
205
+                        case 'turn':
206
+                        case 'turns':
207
+                            dict.url = type + ':';
208
+                            const username = el.attr('username');
209
+                            // https://code.google.com/p/webrtc/issues/detail?id=1508
210
+                            if (username) {
211
+                                if (navigator.userAgent.match(
212
+                                    /Chrom(e|ium)\/([0-9]+)\./)
213
+                                    && parseInt(
214
+                                        navigator.userAgent.match(
215
+                                            /Chrom(e|ium)\/([0-9]+)\./)[2],
216
+                                            10) < 28) {
217
+                                    dict.url += username + '@';
218
+                                } else {
219
+                                    // only works in M28
220
+                                    dict.username = username;
217 221
                                 }
218
-                                iceservers.push(dict);
219
-                                break;
220
-                        }
221
-                    });
222
-                    self.ice_config.iceServers = iceservers;
223
-                },
224
-                function (err) {
225
-                    logger.warn('getting turn credentials failed', err);
226
-                    logger.warn('is mod_turncredentials or similar installed?');
227
-                }
228
-            );
229
-            // implement push?
230
-        },
222
+                            }
223
+                            dict.url += el.attr('host');
224
+                            const port = el.attr('port');
225
+                            if (port && port != '3478') {
226
+                                dict.url += ':' + el.attr('port');
227
+                            }
228
+                            const transport = el.attr('transport');
229
+                            if (transport && transport != 'udp') {
230
+                                dict.url += '?transport=' + transport;
231
+                            }
231 232
 
232
-        /**
233
-         * Returns the data saved in 'updateLog' in a format to be logged.
234
-         */
235
-        getLog: function () {
236
-            var data = {};
237
-            var self = this;
238
-            Object.keys(this.sessions).forEach(function (sid) {
239
-                var session = self.sessions[sid];
240
-                if (session.peerconnection && session.peerconnection.updateLog) {
241
-                    // FIXME: should probably be a .dump call
242
-                    data["jingle_" + session.sid] = {
243
-                        updateLog: session.peerconnection.updateLog,
244
-                        stats: session.peerconnection.stats,
245
-                        url: window.location.href
246
-                    };
247
-                }
233
+                            dict.credential = el.attr('password')
234
+                                || dict.credential;
235
+                            iceservers.push(dict);
236
+                            break;
237
+                    }
238
+                });
239
+                self.ice_config.iceServers = iceservers;
240
+            }, (err) => {
241
+                logger.warn('getting turn credentials failed', err);
242
+                logger.warn('is mod_turncredentials or similar installed?');
248 243
             });
249
-            return data;
250
-        }
251
-    });
244
+        // implement push?
245
+    }
246
+
247
+    /**
248
+     * Returns the data saved in 'updateLog' in a format to be logged.
249
+     */
250
+    getLog () {
251
+        const data = {};
252
+        Object.keys(this.sessions).forEach((sid) => {
253
+            const session = self.sessions[sid];
254
+            const pc = session.peerconnection
255
+            if (pc && pc.updateLog) {
256
+                // FIXME: should probably be a .dump call
257
+                data["jingle_" + sid] = {
258
+                    updateLog: pc.updateLog,
259
+                    stats: pc.stats,
260
+                    url: window.location.href
261
+                };
262
+            }
263
+        });
264
+        return data;
265
+    }
266
+}
267
+
268
+
269
+
270
+module.exports = function(XMPP, eventEmitter) {
271
+    Strophe.addConnectionPlugin('jingle',
272
+        new JingleConnectionPlugin(XMPP, eventEmitter));
252 273
 };

+ 28
- 18
modules/xmpp/strophe.logger.js 查看文件

@@ -1,20 +1,30 @@
1 1
 /* global Strophe */
2
-module.exports = function () {
2
+import ConnectionPlugin from "./ConnectionPlugin";
3 3
 
4
-    Strophe.addConnectionPlugin('logger', {
5
-        // logs raw stanzas and makes them available for download as JSON
6
-        connection: null,
7
-        log: [],
8
-        init: function (conn) {
9
-            this.connection = conn;
10
-            this.connection.rawInput = this.log_incoming.bind(this);
11
-            this.connection.rawOutput = this.log_outgoing.bind(this);
12
-        },
13
-        log_incoming: function (stanza) {
14
-            this.log.push([new Date().getTime(), 'incoming', stanza]);
15
-        },
16
-        log_outgoing: function (stanza) {
17
-            this.log.push([new Date().getTime(), 'outgoing', stanza]);
18
-        }
19
-    });
20
-};
4
+/**
5
+ *  Logs raw stanzas and makes them available for download as JSON
6
+ */
7
+class StropheLogger extends ConnectionPlugin {
8
+    constructor() {
9
+        super();
10
+        this.log = [];
11
+    }
12
+
13
+    init (connection) {
14
+        super.init(connection);
15
+        this.connection.rawInput = this.log_incoming.bind(this);
16
+        this.connection.rawOutput = this.log_outgoing.bind(this);
17
+    }
18
+
19
+    log_incoming (stanza) {
20
+        this.log.push([new Date().getTime(), 'incoming', stanza]);
21
+    }
22
+
23
+    log_outgoing (stanza) {
24
+        this.log.push([new Date().getTime(), 'outgoing', stanza]);
25
+    }
26
+}
27
+
28
+export default function () {
29
+    Strophe.addConnectionPlugin('logger', new StropheLogger());
30
+}

+ 118
- 124
modules/xmpp/strophe.ping.js 查看文件

@@ -1,149 +1,143 @@
1 1
 /* global $, $iq, Strophe */
2
-
3
-var logger = require("jitsi-meet-logger").getLogger(__filename);
4
-var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
5
-var XMPPEvents = require("../../service/xmpp/XMPPEvents");
2
+import {getLogger} from "jitsi-meet-logger";
3
+const logger = getLogger(__filename);
4
+import GlobalOnErrorHandler from "../util/GlobalOnErrorHandler";
5
+import XMPPEvents from "../../service/xmpp/XMPPEvents";
6
+import ConnectionPlugin from "./ConnectionPlugin";
6 7
 
7 8
 /**
8 9
  * Ping every 10 sec
9 10
  */
10
-var PING_INTERVAL = 10000;
11
+const PING_INTERVAL = 10000;
11 12
 
12 13
 /**
13 14
  * Ping timeout error after 15 sec of waiting.
14 15
  */
15
-var PING_TIMEOUT = 15000;
16
+const PING_TIMEOUT = 15000;
16 17
 
17 18
 /**
18 19
  * Will close the connection after 3 consecutive ping errors.
19 20
  */
20
-var PING_THRESHOLD = 3;
21
+const PING_THRESHOLD = 3;
22
+
23
+
24
+
21 25
 
22 26
 /**
23 27
  * XEP-0199 ping plugin.
24 28
  *
25 29
  * Registers "urn:xmpp:ping" namespace under Strophe.NS.PING.
26 30
  */
27
-module.exports = function (XMPP, eventEmitter) {
28
-    Strophe.addConnectionPlugin('ping', {
29
-
30
-        connection: null,
31
-
32
-        failedPings: 0,
31
+class PingConnectionPlugin extends ConnectionPlugin {
32
+    constructor() {
33
+        super();
34
+        this.failedPings = 0;
35
+    }
33 36
 
34
-        /**
35
-         * Initializes the plugin. Method called by Strophe.
36
-         * @param connection Strophe connection instance.
37
-         */
38
-        init: function (connection) {
39
-            this.connection = connection;
40
-            Strophe.addNamespace('PING', "urn:xmpp:ping");
41
-        },
37
+    /**
38
+     * Initializes the plugin. Method called by Strophe.
39
+     * @param connection Strophe connection instance.
40
+     */
41
+    init (connection) {
42
+        super.init(connection);
43
+        Strophe.addNamespace('PING', "urn:xmpp:ping");
44
+    }
42 45
 
43
-        /**
44
-         * Sends "ping" to given <tt>jid</tt>
45
-         * @param jid the JID to which ping request will be sent.
46
-         * @param success callback called on success.
47
-         * @param error callback called on error.
48
-         * @param timeout ms how long are we going to wait for the response. On
49
-         *        timeout <tt>error<//t> callback is called with undefined error
50
-         *        argument.
51
-         */
52
-        ping: function (jid, success, error, timeout) {
53
-            var iq = $iq({type: 'get', to: jid});
54
-            iq.c('ping', {xmlns: Strophe.NS.PING});
55
-            this.connection.sendIQ(iq, success, error, timeout);
56
-        },
46
+    /**
47
+     * Sends "ping" to given <tt>jid</tt>
48
+     * @param jid the JID to which ping request will be sent.
49
+     * @param success callback called on success.
50
+     * @param error callback called on error.
51
+     * @param timeout ms how long are we going to wait for the response. On
52
+     *        timeout <tt>error<//t> callback is called with undefined error
53
+     *        argument.
54
+     */
55
+    ping (jid, success, error, timeout) {
56
+        const iq = $iq({type: 'get', to: jid});
57
+        iq.c('ping', {xmlns: Strophe.NS.PING});
58
+        this.connection.sendIQ(iq, success, error, timeout);
59
+    }
57 60
 
58
-        /**
59
-         * Checks if given <tt>jid</tt> has XEP-0199 ping support.
60
-         * @param jid the JID to be checked for ping support.
61
-         * @param callback function with boolean argument which will be
62
-         * <tt>true</tt> if XEP-0199 ping is supported by given <tt>jid</tt>
63
-         */
64
-        hasPingSupport: function (jid, callback) {
65
-            var disco = this.connection.disco;
66
-            // XXX The following disco.info was observed to throw a "TypeError:
67
-            // Cannot read property 'info' of undefined" during porting to React
68
-            // Native. Since disco is checked in multiple places (e.g.
69
-            // strophe.jingle.js, strophe.rayo.js), check it here as well.
70
-            if (disco) {
71
-                disco.info(
72
-                    jid,
73
-                    null,
74
-                    function (result) {
75
-                        var ping
76
-                            = $(result).find('>>feature[var="urn:xmpp:ping"]');
77
-                        callback(ping.length > 0);
78
-                    },
79
-                    function (error) {
80
-                        var errmsg = "Ping feature discovery error";
81
-                        GlobalOnErrorHandler.callErrorHandler(new Error(
82
-                            errmsg + ": " + error));
83
-                        logger.error(errmsg, error);
84
-                        callback(false);
85
-                    }
86
-                );
87
-            } else {
88
-              // FIXME Should callback be invoked here? Maybe with false as an
89
-              // argument?
90
-            }
91
-        },
92
-
93
-        /**
94
-         * Starts to send ping in given interval to specified remote JID.
95
-         * This plugin supports only one such task and <tt>stopInterval</tt>
96
-         * must be called before starting a new one.
97
-         * @param remoteJid remote JID to which ping requests will be sent to.
98
-         * @param interval task interval in ms.
99
-         */
100
-        startInterval: function (remoteJid, interval) {
101
-            if (this.intervalId) {
102
-                var errmsg = "Ping task scheduled already";
103
-                GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
104
-                logger.error(errmsg);
105
-                return;
106
-            }
107
-            if (!interval)
108
-                interval = PING_INTERVAL;
109
-            var self = this;
110
-            this.intervalId = window.setInterval(function () {
111
-                self.ping(remoteJid,
112
-                function (result) {
113
-                    // Ping OK
114
-                    self.failedPings = 0;
115
-                },
116
-                function (error) {
117
-                    self.failedPings += 1;
118
-                    var errmsg = "Ping " + (error ? "error" : "timeout");
119
-                    if (self.failedPings >= PING_THRESHOLD) {
120
-                        GlobalOnErrorHandler.callErrorHandler(
121
-                            new Error(errmsg));
122
-                        logger.error(errmsg, error);
123
-                        // FIXME it doesn't help to disconnect when 3rd PING
124
-                        // times out, it only stops Strophe from retrying.
125
-                        // Not really sure what's the right thing to do in that
126
-                        // situation, but just closing the connection makes no
127
-                        // sense.
128
-                        //self.connection.disconnect();
129
-                    } else {
130
-                        logger.warn(errmsg, error);
131
-                    }
132
-                }, PING_TIMEOUT);
133
-            }, interval);
134
-            logger.info("XMPP pings will be sent every " + interval + " ms");
135
-        },
61
+    /**
62
+     * Checks if given <tt>jid</tt> has XEP-0199 ping support.
63
+     * @param jid the JID to be checked for ping support.
64
+     * @param callback function with boolean argument which will be
65
+     * <tt>true</tt> if XEP-0199 ping is supported by given <tt>jid</tt>
66
+     */
67
+    hasPingSupport (jid, callback) {
68
+        const disco = this.connection.disco;
69
+        // XXX The following disco.info was observed to throw a "TypeError:
70
+        // Cannot read property 'info' of undefined" during porting to React
71
+        // Native. Since disco is checked in multiple places (e.g.
72
+        // strophe.jingle.js, strophe.rayo.js), check it here as well.
73
+        if (disco) {
74
+            disco.info(jid, null, (result)  => {
75
+                const ping
76
+                    = $(result).find('>>feature[var="urn:xmpp:ping"]');
77
+                callback(ping.length > 0);
78
+            }, (error) => {
79
+                const errmsg = "Ping feature discovery error";
80
+                GlobalOnErrorHandler.callErrorHandler(new Error(
81
+                    errmsg + ": " + error));
82
+                logger.error(errmsg, error);
83
+                callback(false);
84
+            });
85
+        } else {
86
+          // FIXME Should callback be invoked here? Maybe with false as an
87
+          // argument?
88
+        }
89
+    }
136 90
 
137
-        /**
138
-         * Stops current "ping"  interval task.
139
-         */
140
-        stopInterval: function () {
141
-            if (this.intervalId) {
142
-                window.clearInterval(this.intervalId);
143
-                this.intervalId = null;
91
+    /**
92
+     * Starts to send ping in given interval to specified remote JID.
93
+     * This plugin supports only one such task and <tt>stopInterval</tt>
94
+     * must be called before starting a new one.
95
+     * @param remoteJid remote JID to which ping requests will be sent to.
96
+     * @param interval task interval in ms.
97
+     */
98
+    startInterval (remoteJid, interval = PING_INTERVAL) {
99
+        if (this.intervalId) {
100
+            const errmsg = "Ping task scheduled already";
101
+            GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
102
+            logger.error(errmsg);
103
+            return;
104
+        }
105
+        this.intervalId = window.setInterval(() => {
106
+            this.ping(remoteJid, (result) => {
144 107
                 this.failedPings = 0;
145
-                logger.info("Ping interval cleared");
146
-            }
108
+            }, (error) => {
109
+                this.failedPings += 1;
110
+                const errmsg = "Ping " + (error ? "error" : "timeout");
111
+                if (this.failedPings >= PING_THRESHOLD) {
112
+                    GlobalOnErrorHandler.callErrorHandler(new Error(errmsg));
113
+                    logger.error(errmsg, error);
114
+                    // FIXME it doesn't help to disconnect when 3rd PING
115
+                    // times out, it only stops Strophe from retrying.
116
+                    // Not really sure what's the right thing to do in that
117
+                    // situation, but just closing the connection makes no
118
+                    // sense.
119
+                    //self.connection.disconnect();
120
+                } else {
121
+                    logger.warn(errmsg, error);
122
+                }
123
+            }, PING_TIMEOUT);
124
+        }, interval);
125
+        logger.info("XMPP pings will be sent every " + interval + " ms");
126
+    }
127
+
128
+    /**
129
+     * Stops current "ping"  interval task.
130
+     */
131
+    stopInterval () {
132
+        if (this.intervalId) {
133
+            window.clearInterval(this.intervalId);
134
+            this.intervalId = null;
135
+            this.failedPings = 0;
136
+            logger.info("Ping interval cleared");
147 137
         }
148
-    });
149
-};
138
+    }
139
+}
140
+
141
+export default function () {
142
+    Strophe.addConnectionPlugin('ping', new PingConnectionPlugin());
143
+}

+ 87
- 104
modules/xmpp/strophe.rayo.js 查看文件

@@ -1,114 +1,97 @@
1 1
 /* jshint -W117 */
2
-var logger = require("jitsi-meet-logger").getLogger(__filename);
2
+import {getLogger} from "jitsi-meet-logger";
3
+const logger = getLogger(__filename);
4
+import ConnectionPlugin from "./ConnectionPlugin";
3 5
 
4
-module.exports = function() {
5
-    Strophe.addConnectionPlugin('rayo',
6
-        {
7
-            RAYO_XMLNS: 'urn:xmpp:rayo:1',
8
-            connection: null,
9
-            init: function (conn) {
10
-                this.connection = conn;
11
-                var disco = conn.disco;
12
-                if (disco) {
13
-                    disco.addFeature('urn:xmpp:rayo:client:1');
14
-                }
6
+const RAYO_XMLNS = 'urn:xmpp:rayo:1';
15 7
 
16
-                this.connection.addHandler(
17
-                    this.onRayo.bind(this), this.RAYO_XMLNS, 'iq', 'set',
18
-                    null, null);
19
-            },
20
-            onRayo: function (iq) {
21
-                logger.info("Rayo IQ", iq);
22
-            },
23
-            dial: function (to, from, roomName, roomPass, focusMucJid) {
24
-                var self = this;
25
-                return new Promise(function (resolve, reject) {
26
-                    if(!focusMucJid) {
27
-                        reject(new Error("Internal error!"));
28
-                        return;
29
-                    }
30
-                    var req = $iq(
31
-                        {
32
-                            type: 'set',
33
-                            to: focusMucJid
34
-                        }
35
-                    );
36
-                    req.c('dial',
37
-                        {
38
-                            xmlns: self.RAYO_XMLNS,
39
-                            to: to,
40
-                            from: from
41
-                        });
42
-                    req.c('header',
43
-                        {
44
-                            name: 'JvbRoomName',
45
-                            value: roomName
46
-                        }).up();
8
+class RayoConnectionPlugin extends ConnectionPlugin {
9
+    init (connection) {
10
+        super.init(connection);
11
+        const disco = this.connection.disco;
12
+        if (disco) {
13
+            disco.addFeature('urn:xmpp:rayo:client:1');
14
+        }
15
+
16
+        this.connection.addHandler(
17
+            this.onRayo.bind(this), RAYO_XMLNS, 'iq', 'set', null, null);
18
+    }
47 19
 
48
-                    if (roomPass !== null && roomPass.length) {
20
+    onRayo (iq) {
21
+        logger.info("Rayo IQ", iq);
22
+    }
49 23
 
50
-                        req.c('header',
51
-                            {
52
-                                name: 'JvbRoomPassword',
53
-                                value: roomPass
54
-                            }).up();
55
-                    }
24
+    dial (to, from, roomName, roomPass, focusMucJid) {
25
+        return new Promise((resolve, reject) => {
26
+            if(!focusMucJid) {
27
+                reject(new Error("Internal error!"));
28
+                return;
29
+            }
30
+            const req = $iq({
31
+                type: 'set',
32
+                to: focusMucJid
33
+            });
34
+            req.c('dial', {
35
+                xmlns: self.RAYO_XMLNS,
36
+                to: to,
37
+                from: from
38
+            });
39
+            req.c('header', {
40
+                name: 'JvbRoomName',
41
+                value: roomName
42
+            }).up();
56 43
 
57
-                    self.connection.sendIQ(
58
-                        req,
59
-                        function (result) {
60
-                            logger.info('Dial result ', result);
44
+            if (roomPass !== null && roomPass.length) {
45
+                req.c('header', {
46
+                    name: 'JvbRoomPassword',
47
+                    value: roomPass
48
+                }).up();
49
+            }
61 50
 
62
-                            var resource = $(result).find('ref').attr('uri');
63
-                            self.call_resource =
64
-                                resource.substr('xmpp:'.length);
65
-                            logger.info(
66
-                                "Received call resource: " +
67
-                                self.call_resource);
68
-                            resolve();
69
-                        },
70
-                        function (error) {
71
-                            logger.info('Dial error ', error);
72
-                            reject(error);
73
-                        }
74
-                    );
75
-                });
76
-            },
77
-            hangup: function () {
78
-                var self = this;
79
-                return new Promise(function (resolve, reject) {
80
-                    if (!self.call_resource) {
81
-                        reject(new Error("No call in progress"));
82
-                        logger.warn("No call in progress");
83
-                        return;
84
-                    }
51
+            this.connection.sendIQ(req, (result) => {
52
+                logger.info('Dial result ', result);
85 53
 
86
-                    var req = $iq(
87
-                        {
88
-                            type: 'set',
89
-                            to: self.call_resource
90
-                        }
91
-                    );
92
-                    req.c('hangup',
93
-                        {
94
-                            xmlns: self.RAYO_XMLNS
95
-                        });
54
+                let resource = $(result).find('ref').attr('uri');
55
+                this.call_resource =
56
+                    resource.substr('xmpp:'.length);
57
+                logger.info("Received call resource: " + this.call_resource);
58
+                resolve();
59
+            }, (error) => {
60
+                logger.info('Dial error ', error);
61
+                reject(error);
62
+            });
63
+        });
64
+    }
96 65
 
97
-                    self.connection.sendIQ(
98
-                        req,
99
-                        function (result) {
100
-                            logger.info('Hangup result ', result);
101
-                            self.call_resource = null;
102
-                            resolve();
103
-                        },
104
-                        function (error) {
105
-                            logger.info('Hangup error ', error);
106
-                            self.call_resource = null;
107
-                            reject(new Error('Hangup error '));
108
-                        }
109
-                    );
110
-                });
66
+    hangup () {
67
+        return new Promise((resolve, reject) => {
68
+            if (!this.call_resource) {
69
+                reject(new Error("No call in progress"));
70
+                logger.warn("No call in progress");
71
+                return;
111 72
             }
112
-        }
113
-    );
114
-};
73
+
74
+            const req = $iq({
75
+                type: 'set',
76
+                to: this.call_resource
77
+            });
78
+            req.c('hangup', {
79
+                xmlns: RAYO_XMLNS
80
+            });
81
+
82
+            this.connection.sendIQ(req, (result) => {
83
+                logger.info('Hangup result ', result);
84
+                this.call_resource = null;
85
+                resolve();
86
+            }, (error) => {
87
+                logger.info('Hangup error ', error);
88
+                this.call_resource = null;
89
+                reject(new Error('Hangup error '));
90
+            });
91
+        });
92
+    }
93
+}
94
+
95
+export default function() {
96
+    Strophe.addConnectionPlugin('rayo', new RayoConnectionPlugin());
97
+}

+ 5
- 4
modules/xmpp/strophe.util.js 查看文件

@@ -2,10 +2,11 @@
2 2
 /**
3 3
  * Strophe logger implementation. Logs from level WARN and above.
4 4
  */
5
-var logger = require("jitsi-meet-logger").getLogger(__filename);
6
-var GlobalOnErrorHandler = require("../util/GlobalOnErrorHandler");
5
+import {getLogger} from "jitsi-meet-logger";
6
+const logger = getLogger(__filename);
7
+import GlobalOnErrorHandler from "../util/GlobalOnErrorHandler";
7 8
 
8
-module.exports = function () {
9
+export default function () {
9 10
 
10 11
     Strophe.log = function (level, msg) {
11 12
         // Our global handler reports uncaught errors to the stats which may
@@ -55,4 +56,4 @@ module.exports = function () {
55 56
                 return "unknown";
56 57
         }
57 58
     };
58
-};
59
+}

+ 307
- 335
modules/xmpp/xmpp.js 查看文件

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

Loading…
取消
儲存