浏览代码

feat(caps): Implement XEP-0115

master
hristoterezov 8 年前
父节点
当前提交
3f43e1e4e5

+ 5
- 17
JitsiConference.js 查看文件

@@ -1,4 +1,4 @@
1
-/* global Strophe, $, Promise */
1
+/* global Strophe, Promise */
2 2
 
3 3
 var logger = require("jitsi-meet-logger").getLogger(__filename);
4 4
 import RTC from "./modules/RTC/RTC";
@@ -722,22 +722,10 @@ JitsiConference.prototype.onMemberJoined
722 722
     participant._role = role;
723 723
     this.participants[id] = participant;
724 724
     this.eventEmitter.emit(JitsiConferenceEvents.USER_JOINED, id, participant);
725
-    // XXX Since disco is checked in multiple places (e.g.
726
-    // modules/xmpp/strophe.jingle.js, modules/xmpp/strophe.rayo.js), check it
727
-    // here as well.
728
-    var disco = this.xmpp.connection.disco;
729
-    if (disco) {
730
-        disco.info(
731
-            jid, "node", function(iq) {
732
-                participant._supportsDTMF = $(iq).find(
733
-                    '>query>feature[var="urn:xmpp:jingle:dtmf:0"]').length > 0;
734
-                this.updateDTMFSupport();
735
-            }.bind(this)
736
-        );
737
-    } else {
738
-      // FIXME Should participant._supportsDTMF be assigned false here (and
739
-      // this.updateDTMFSupport invoked)?
740
-    }
725
+    this.xmpp.caps.getFeatures(jid).then(features => {
726
+        participant._supportsDTMF = features.has("urn:xmpp:jingle:dtmf:0");
727
+        this.updateDTMFSupport();
728
+    }, error => logger.error(error));
741 729
 };
742 730
 
743 731
 JitsiConference.prototype.onMemberLeft = function (jid) {

+ 22
- 0
JitsiConnection.js 查看文件

@@ -118,4 +118,26 @@ JitsiConnection.prototype.getConnectionTimes = function () {
118 118
     return this.xmpp.connectionTimes;
119 119
 };
120 120
 
121
+/**
122
+ * Adds new feature to the list of supported features for the local
123
+ * participant.
124
+ * @param {String} feature the name of the feature.
125
+ * @param {boolean} submit if true - the new list of features will be
126
+ * immediately submitted to the others.
127
+ */
128
+JitsiConnection.prototype.addFeature = function(feature, submit = false) {
129
+    return this.xmpp.caps.addFeature(feature, submit);
130
+};
131
+
132
+/**
133
+ * Removes a feature from the list of supported features for the local
134
+ * participant
135
+ * @param {String} feature the name of the feature.
136
+ * @param {boolean} submit if true - the new list of features will be
137
+ * immediately submitted to the others.
138
+ */
139
+JitsiConnection.prototype.removeFeature = function (feature, submit = false) {
140
+    return this.xmpp.caps.removeFeature(feature, submit);
141
+};
142
+
121 143
 module.exports = JitsiConnection;

+ 9
- 0
JitsiParticipant.js 查看文件

@@ -257,4 +257,13 @@ export default class JitsiParticipant {
257 257
     supportsDTMF() {
258 258
         return this._supportsDTMF;
259 259
     }
260
+
261
+    /**
262
+     * Returns a set with the features for the participant.
263
+     * @param {int} timeout the timeout in ms for reply from the participant.
264
+     * @returns {Promise<Set<String>, Error>}
265
+     */
266
+    getFeatures(timeout = 5000) {
267
+        return this.conference.xmpp.caps.getFeatures(this._jid, timeout);
268
+    }
260 269
 }

+ 8
- 0
doc/API.md 查看文件

@@ -232,6 +232,14 @@ This objects represents the server connection. You can create new ```JitsiConnec
232 232
     - event - the event
233 233
     - listener - the listener that will be removed.
234 234
 
235
+7. addFeature - Adds new feature to the list of supported features for the local participant
236
+    - feature - string, the name of the feature
237
+    - submit - boolean, default false, if true - the new list of features will be immediately submitted to the others.
238
+
239
+8. removeFeature - Removes a feature from the list of supported features for the local participant
240
+    - feature - string, the name of the feature
241
+    - submit - boolean, default false, if true - the new list of features will be immediately submitted to the others.
242
+
235 243
 JitsiConference
236 244
 -----------
237 245
 The object represents a conference. We have the following methods to control the conference:

+ 1
- 2
doc/example/index.html 查看文件

@@ -4,9 +4,8 @@
4 4
     <meta charset="UTF-8">
5 5
     <title></title>
6 6
     <script src="libs/jquery-2.1.1.min.js"></script>
7
-    <script src="libs/strophe/strophe.min.js"></script>
7
+    <script src="libs/strophe/strophe.js"></script>
8 8
     <script src="libs/strophe/strophe.disco.min.js?v=1"></script>
9
-    <script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>
10 9
     <script src="../../lib-jitsi-meet.js"></script>
11 10
     <script src="example.js" ></script>
12 11
 </head>

+ 0
- 1
doc/example/libs/strophe/strophe.caps.jsonly.min.js 查看文件

@@ -1 +0,0 @@
1
-Strophe.addConnectionPlugin("caps",{HASH:"sha-1",node:"http://strophe.im/strophejs/",_ver:"",_connection:null,_knownCapabilities:{},_jidVerIndex:{},init:function(conn){this._connection=conn;Strophe.addNamespace("CAPS","http://jabber.org/protocol/caps");if(!this._connection.disco){throw"Caps plugin requires the disco plugin to be installed."}this._connection.disco.addFeature(Strophe.NS.CAPS);this._connection.addHandler(this._delegateCapabilities.bind(this),Strophe.NS.CAPS)},generateCapsAttrs:function(){return{xmlns:Strophe.NS.CAPS,hash:this.HASH,node:this.node,ver:this.generateVer()}},generateVer:function(){if(this._ver!==""){return this._ver}var ver="",identities=this._connection.disco._identities.sort(this._sortIdentities),identitiesLen=identities.length,features=this._connection.disco._features.sort(),featuresLen=features.length;for(var i=0;i<identitiesLen;i++){var curIdent=identities[i];ver+=curIdent.category+"/"+curIdent.type+"/"+curIdent.lang+"/"+curIdent.name+"<"}for(var i=0;i<featuresLen;i++){ver+=features[i]+"<"}this._ver=b64_sha1(ver);return this._ver},getCapabilitiesByJid:function(jid){if(this._jidVerIndex[jid]){return this._knownCapabilities[this._jidVerIndex[jid]]}return null},_delegateCapabilities:function(stanza){var from=stanza.getAttribute("from"),c=stanza.querySelector("c"),ver=c.getAttribute("ver"),node=c.getAttribute("node");if(!this._knownCapabilities[ver]){return this._requestCapabilities(from,node,ver)}else{this._jidVerIndex[from]=ver}if(!this._jidVerIndex[from]||!this._jidVerIndex[from]!==ver){this._jidVerIndex[from]=ver}return true},_requestCapabilities:function(to,node,ver){if(to!==this._connection.jid){var id=this._connection.disco.info(to,node+"#"+ver);this._connection.addHandler(this._handleDiscoInfoReply.bind(this),Strophe.NS.DISCO_INFO,"iq","result",id,to)}return true},_handleDiscoInfoReply:function(stanza){var query=stanza.querySelector("query"),node=query.getAttribute("node").split("#"),ver=node[1],from=stanza.getAttribute("from");if(!this._knownCapabilities[ver]){var childNodes=query.childNodes,childNodesLen=childNodes.length;this._knownCapabilities[ver]=[];for(var i=0;i<childNodesLen;i++){var node=childNodes[i];this._knownCapabilities[ver].push({name:node.nodeName,attributes:node.attributes})}this._jidVerIndex[from]=ver}else{if(!this._jidVerIndex[from]||!this._jidVerIndex[from]!==ver){this._jidVerIndex[from]=ver}}return false},_sortIdentities:function(a,b){if(a.category>b.category){return 1}if(a.category<b.category){return -1}if(a.type>b.type){return 1}if(a.type<b.type){return -1}if(a.lang>b.lang){return 1}if(a.lang<b.lang){return -1}return 0}});

+ 210
- 0
modules/xmpp/Caps.js 查看文件

@@ -0,0 +1,210 @@
1
+/* global $, b64_sha1, Strophe */
2
+import XMPPEvents from "../../service/xmpp/XMPPEvents";
3
+
4
+/**
5
+ * The property
6
+ */
7
+const IDENTITY_PROPERTIES = ["category", "type", "lang", "name"];
8
+const IDENTITY_PROPERTIES_FOR_COMPARE = ["category", "type", "lang"];
9
+const HASH = "sha-1";
10
+
11
+function compareIdentities(a, b) {
12
+    let res = 0;
13
+    IDENTITY_PROPERTIES_FOR_COMPARE.some(key =>
14
+        (res = ((a[key] > b[key]) && 1) || ((a[key] < b[key]) && -1)) !== 0
15
+    );
16
+    return res;
17
+}
18
+
19
+/**
20
+ * Implements xep-0115 ( http://xmpp.org/extensions/xep-0115.html )
21
+ */
22
+export default class Caps {
23
+    /**
24
+     * Constructs new Caps instance.
25
+     * @param {Strophe.Connection} connection the strophe connection object
26
+     * @param {String} node the value of the node attribute of the "c" xml node
27
+     * that will be sent to the other participants
28
+     */
29
+    constructor(connection = {}, node = "http://jitsi.org/jitsimeet") {
30
+        this.node = node;
31
+        this.disco = connection.disco;
32
+        if(!this.disco) {
33
+            throw new Error(
34
+                "Missing strophe-plugins "
35
+                + "(disco and caps plugins are required)!");
36
+        }
37
+
38
+        this.versionToCapabilities = Object.create(null);
39
+        this.jidToVersion = Object.create(null);
40
+        this.version = "";
41
+        this.rooms = new Set();
42
+
43
+        const emuc = connection.emuc;
44
+        emuc.addListener(XMPPEvents.EMUC_ROOM_ADDED,
45
+            room => this._addChatRoom(room));
46
+        emuc.addListener(XMPPEvents.EMUC_ROOM_REMOVED,
47
+            room => this._removeChatRoom(room));
48
+        for(let jid in emuc.rooms) {
49
+            this._addChatRoom(this.emuc.rooms[jid]);
50
+        }
51
+
52
+        Strophe.addNamespace("CAPS", "http://jabber.org/protocol/caps");
53
+        this.disco.addFeature(Strophe.NS.CAPS);
54
+        connection.addHandler(this._handleCaps.bind(this), Strophe.NS.CAPS);
55
+
56
+        this._onMucMemberLeft = this._removeJidToVersionEntry.bind(this);
57
+    }
58
+
59
+    /**
60
+     * Adds new feature to the list of supported features for the local
61
+     * participant
62
+     * @param {String} feature the name of the feature.
63
+     * @param {boolean} submit if true - new presence with updated "c" node
64
+     * will be sent.
65
+     */
66
+    addFeature(feature, submit = false) {
67
+        this.disco.addFeature(feature);
68
+        this._generateVersion();
69
+        if(submit) {
70
+            this.submit();
71
+        }
72
+    }
73
+
74
+    /**
75
+     * Removes a feature from the list of supported features for the local
76
+     * participant
77
+     * @param {String} feature the name of the feature.
78
+     * @param {boolean} submit if true - new presence with updated "c" node
79
+     * will be sent.
80
+     */
81
+    removeFeature(feature, submit = false) {
82
+        this.disco.removeFeature(feature);
83
+        this._generateVersion();
84
+        if(submit) {
85
+            this.submit();
86
+        }
87
+    }
88
+
89
+    /**
90
+     * Sends new presence stanza for every room from the list of rooms.
91
+     */
92
+    submit() {
93
+        this.rooms.forEach(room => room.sendPresence());
94
+    }
95
+
96
+    /**
97
+     * Returns a set with the features for a participant.
98
+     * @param {String} jid the jid of the participant
99
+     * @param {int} timeout the timeout in ms for reply from the participant.
100
+     * @returns {Promise<Set<String>, Error>}
101
+     */
102
+    getFeatures(jid, timeout = 5000) {
103
+        let user
104
+            = (jid in this.jidToVersion) ? this.jidToVersion[jid] : null;
105
+        if(!user || !(user.version in this.versionToCapabilities))
106
+        {
107
+            const node = (user)? user.node + "#" + user.version : null;
108
+            return new Promise ( (resolve, reject) =>
109
+                this.disco.info(jid, node, response => {
110
+                        const features = new Set();
111
+                        $(response).find(">query>feature").each((idx, el) =>
112
+                            features.add(el.getAttribute("var")));
113
+                        if(user) {
114
+                            this.versionToCapabilities[user.version]
115
+                                = features;
116
+                        }
117
+                        resolve(features);
118
+                    }, reject , timeout)
119
+            );
120
+        }
121
+        return Promise.resolve(this.versionToCapabilities[user.version]);
122
+    }
123
+
124
+    /**
125
+     * Adds ChatRoom instance to the list of rooms. Adds listeners to the room
126
+     * and adds "c" element to the presences of the room.
127
+     * @param {ChatRoom} room the room.
128
+     */
129
+    _addChatRoom(room) {
130
+        this.rooms.add(room);
131
+        room.addListener(XMPPEvents.MUC_MEMBER_LEFT, this._onMucMemberLeft);
132
+        this._fixChatRoomPresenceMap(room);
133
+    }
134
+
135
+    /**
136
+     * Removes ChatRoom instance from the list of rooms. Removes listeners
137
+     * added from the Caps class.
138
+     * @param {ChatRoom} room the room.
139
+     */
140
+    _removeChatRoom(room) {
141
+        this.rooms.delete(room);
142
+        room.removeListener(XMPPEvents.MUC_MEMBER_LEFT, this._onMucMemberLeft);
143
+    }
144
+
145
+    /**
146
+     * Creates/updates the "c" xml node into the presence of the passed room.
147
+     * @param {ChatRoom} room the room.
148
+     */
149
+    _fixChatRoomPresenceMap(room) {
150
+        room.addToPresence("c", {
151
+            attributes: {
152
+                xmlns: Strophe.NS.CAPS,
153
+                hash: HASH,
154
+                node: this.node,
155
+                ver: this.version
156
+            }
157
+        });
158
+    }
159
+
160
+    /**
161
+     * Handles this.version changes.
162
+     */
163
+    _notifyVersionChanged() {
164
+        //update the version for all rooms
165
+        this.rooms.forEach(room => this._fixChatRoomPresenceMap(room));
166
+        this.submit();
167
+    }
168
+
169
+    /**
170
+     * Generates the value for the "ver" attribute.
171
+     */
172
+    _generateVersion() {
173
+        const identities = this.disco._identities.sort(compareIdentities);
174
+        const features = this.disco._features.sort();
175
+        this.version = b64_sha1(
176
+            identities.reduce(
177
+                (accumulatedValue, identity) => {
178
+                    return IDENTITY_PROPERTIES.reduce((tmp, key, idx) => {
179
+                        return (idx === 0 ? "" : "/") + identity[key];
180
+                    }, "") + "<";
181
+                }, ""
182
+            ) + features.reduce((tmp, feature) => feature + "<", "")
183
+        );
184
+        this._notifyVersionChanged();
185
+    }
186
+
187
+    /**
188
+     * Parses the "c" xml node from presence.
189
+     * @param {DOMElement} stanza the presence packet
190
+     */
191
+    _handleCaps(stanza) {
192
+        const from = stanza.getAttribute("from");
193
+        const caps = stanza.querySelector("c");
194
+        const version = caps.getAttribute("ver");
195
+        const node = caps.getAttribute("node");
196
+        this.jidToVersion[from] = {version, node};
197
+        // return true to not remove the handler from Strophe
198
+        return true;
199
+    }
200
+
201
+    /**
202
+     * Removes entry from this.jidToVersion map.
203
+     * @param {String} jid the jid to be removed.
204
+     */
205
+    _removeJidToVersionEntry(jid) {
206
+        if(jid in this.jidToVersion) {
207
+            delete this.jidToVersion[jid];
208
+        }
209
+    }
210
+}

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

@@ -152,22 +152,14 @@ export default class ChatRoom extends Listenable {
152 152
             pres.up();
153 153
         }
154 154
 
155
-        // Send XEP-0115 'c' stanza that contains our capabilities info
156
-        var connection = this.connection;
157
-        var caps = connection.caps;
158
-        if (caps) {
159
-            caps.node = this.xmpp.options.clientNode;
160
-            pres.c('c', caps.generateCapsAttrs()).up();
161
-        }
162
-
163 155
         parser.JSON2packet(this.presMap.nodes, pres);
164
-        connection.send(pres);
156
+        this.connection.send(pres);
165 157
         if (fromJoin) {
166 158
             // XXX We're pressed for time here because we're beginning a complex
167 159
             // and/or lengthy conference-establishment process which supposedly
168 160
             // involves multiple RTTs. We don't have the time to wait for Strophe to
169 161
             // decide to send our IQ.
170
-            connection.flush();
162
+            this.connection.flush();
171 163
         }
172 164
     }
173 165
 

+ 29
- 8
modules/xmpp/ConnectionPlugin.js 查看文件

@@ -1,11 +1,32 @@
1
+import Listenable from "../util/Listenable";
2
+
1 3
 /**
2
- * Base class for strophe connection plugins.
4
+ * Creates ConnectionPlugin class that extends the passed class.
5
+ * @param {Class} base the definition of the class that will be extended by
6
+ * ConnectionPlugin
3 7
  */
4
-export default class ConnectionPlugin {
5
-    constructor() {
6
-        this.connection = null;
7
-    }
8
-    init (connection) {
9
-        this.connection = connection;
10
-    }
8
+function getConnectionPluginDefinition(base = class{}) {
9
+    /**
10
+     * Base class for strophe connection plugins.
11
+     */
12
+    return class extends base {
13
+        constructor(...args) {
14
+            super(...args);
15
+            this.connection = null;
16
+        }
17
+        init (connection) {
18
+            this.connection = connection;
19
+        }
20
+    };
11 21
 }
22
+
23
+/**
24
+ * ConnectionPlugin class.
25
+ */
26
+export default getConnectionPluginDefinition();
27
+
28
+/**
29
+ * ConnectionPlugin class that extends Listenable.
30
+ */
31
+export const ConnectionPluginListenable
32
+    = getConnectionPluginDefinition(Listenable);

+ 7
- 2
modules/xmpp/strophe.emuc.js 查看文件

@@ -7,9 +7,10 @@
7 7
 import {getLogger} from "jitsi-meet-logger";
8 8
 const logger = getLogger(__filename);
9 9
 import ChatRoom from "./ChatRoom";
10
-import ConnectionPlugin from "./ConnectionPlugin";
10
+import {ConnectionPluginListenable} from "./ConnectionPlugin";
11
+import XMPPEvents from "../../service/xmpp/XMPPEvents";
11 12
 
12
-class MucConnectionPlugin extends ConnectionPlugin {
13
+class MucConnectionPlugin extends ConnectionPluginListenable {
13 14
     constructor(xmpp) {
14 15
         super();
15 16
         this.xmpp = xmpp;
@@ -40,10 +41,14 @@ class MucConnectionPlugin extends ConnectionPlugin {
40 41
         }
41 42
         this.rooms[roomJid] = new ChatRoom(this.connection, jid,
42 43
             password, this.xmpp, options);
44
+        this.eventEmitter.emit(
45
+            XMPPEvents.EMUC_ROOM_ADDED, this.rooms[roomJid]);
43 46
         return this.rooms[roomJid];
44 47
     }
45 48
 
46 49
     doLeave (jid) {
50
+        this.eventEmitter.emit(
51
+            XMPPEvents.EMUC_ROOM_REMOVED, this.rooms[jid]);
47 52
         delete this.rooms[jid];
48 53
     }
49 54
 

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

@@ -1,4 +1,4 @@
1
-/* global $, $iq, Strophe */
1
+/* global $iq, Strophe */
2 2
 
3 3
 import { getLogger } from "jitsi-meet-logger";
4 4
 const logger = getLogger(__filename);
@@ -20,18 +20,21 @@ const PING_TIMEOUT = 15000;
20 20
  */
21 21
 const PING_THRESHOLD = 3;
22 22
 
23
-
24
-
25
-
26 23
 /**
27 24
  * XEP-0199 ping plugin.
28 25
  *
29 26
  * Registers "urn:xmpp:ping" namespace under Strophe.NS.PING.
30 27
  */
31 28
 class PingConnectionPlugin extends ConnectionPlugin {
32
-    constructor() {
29
+    /**
30
+     * Contructs new object
31
+     * @param {XMPP} xmpp the xmpp module.
32
+     * @constructor
33
+     */
34
+    constructor(xmpp) {
33 35
         super();
34 36
         this.failedPings = 0;
37
+        this.xmpp = xmpp;
35 38
     }
36 39
 
37 40
     /**
@@ -65,27 +68,14 @@ class PingConnectionPlugin extends ConnectionPlugin {
65 68
      * <tt>true</tt> if XEP-0199 ping is supported by given <tt>jid</tt>
66 69
      */
67 70
     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
-        }
71
+        this.xmpp.caps.getFeatures(jid).then(features =>
72
+            callback(features.has("urn:xmpp:ping")), error => {
73
+            const errmsg = "Ping feature discovery error";
74
+            GlobalOnErrorHandler.callErrorHandler(new Error(
75
+                errmsg + ": " + error));
76
+            logger.error(errmsg, error);
77
+            callback(false);
78
+        });
89 79
     }
90 80
 
91 81
     /**
@@ -138,6 +128,6 @@ class PingConnectionPlugin extends ConnectionPlugin {
138 128
     }
139 129
 }
140 130
 
141
-export default function () {
142
-    Strophe.addConnectionPlugin('ping', new PingConnectionPlugin());
131
+export default function (xmpp) {
132
+    Strophe.addConnectionPlugin('ping', new PingConnectionPlugin(xmpp));
143 133
 }

+ 0
- 4
modules/xmpp/strophe.rayo.js 查看文件

@@ -9,10 +9,6 @@ const RAYO_XMLNS = 'urn:xmpp:rayo:1';
9 9
 class RayoConnectionPlugin extends ConnectionPlugin {
10 10
     init (connection) {
11 11
         super.init(connection);
12
-        const disco = this.connection.disco;
13
-        if (disco) {
14
-            disco.addFeature('urn:xmpp:rayo:client:1');
15
-        }
16 12
 
17 13
         this.connection.addHandler(
18 14
             this.onRayo.bind(this), RAYO_XMLNS, 'iq', 'set', null, null);

+ 23
- 22
modules/xmpp/xmpp.js 查看文件

@@ -13,6 +13,7 @@ import initPing from "./strophe.ping";
13 13
 import initRayo from "./strophe.rayo";
14 14
 import initStropheLogger from "./strophe.logger";
15 15
 import Listenable from "../util/Listenable";
16
+import Caps from "./Caps";
16 17
 
17 18
 function createConnection(token, bosh = '/http-bind') {
18 19
     // Append token as URL param
@@ -38,9 +39,7 @@ export default class XMPP extends Listenable {
38 39
 
39 40
         this.connection = createConnection(token, options.bosh);
40 41
 
41
-        if(!this.connection.disco || !this.connection.caps)
42
-            throw new Error(
43
-                "Missing strophe-plugins (disco and caps plugins are required)!");
42
+        this.caps = new Caps(this.connection, this.options.clientNode);
44 43
 
45 44
         // Initialize features advertised in disco-info
46 45
         this.initFeaturesList();
@@ -57,38 +56,40 @@ export default class XMPP extends Listenable {
57 56
      * Initializes the list of feature advertised through the disco-info mechanism
58 57
      */
59 58
     initFeaturesList () {
60
-        const disco = this.connection.disco;
61
-        if (!disco)
62
-            return;
63
-
64 59
         // http://xmpp.org/extensions/xep-0167.html#support
65 60
         // http://xmpp.org/extensions/xep-0176.html#support
66
-        disco.addFeature('urn:xmpp:jingle:1');
67
-        disco.addFeature('urn:xmpp:jingle:apps:rtp:1');
68
-        disco.addFeature('urn:xmpp:jingle:transports:ice-udp:1');
69
-        disco.addFeature('urn:xmpp:jingle:apps:dtls:0');
70
-        disco.addFeature('urn:xmpp:jingle:transports:dtls-sctp:1');
71
-        disco.addFeature('urn:xmpp:jingle:apps:rtp:audio');
72
-        disco.addFeature('urn:xmpp:jingle:apps:rtp:video');
61
+        this.caps.addFeature('urn:xmpp:jingle:1');
62
+        this.caps.addFeature('urn:xmpp:jingle:apps:rtp:1');
63
+        this.caps.addFeature('urn:xmpp:jingle:transports:ice-udp:1');
64
+        this.caps.addFeature('urn:xmpp:jingle:apps:dtls:0');
65
+        this.caps.addFeature('urn:xmpp:jingle:transports:dtls-sctp:1');
66
+        this.caps.addFeature('urn:xmpp:jingle:apps:rtp:audio');
67
+        this.caps.addFeature('urn:xmpp:jingle:apps:rtp:video');
73 68
 
74 69
         if (RTCBrowserType.isChrome() || RTCBrowserType.isOpera()
75 70
             || RTCBrowserType.isTemasysPluginUsed()) {
76
-            disco.addFeature('urn:ietf:rfc:4588');
71
+            this.caps.addFeature('urn:ietf:rfc:4588');
77 72
         }
78 73
 
79 74
         // this is dealt with by SDP O/A so we don't need to announce this
80
-        //disco.addFeature('urn:xmpp:jingle:apps:rtp:rtcp-fb:0'); // XEP-0293
81
-        //disco.addFeature('urn:xmpp:jingle:apps:rtp:rtp-hdrext:0'); // XEP-0294
75
+        // XEP-0293
76
+        //this.caps.addFeature('urn:xmpp:jingle:apps:rtp:rtcp-fb:0');
77
+        // XEP-0294
78
+        //this.caps.addFeature('urn:xmpp:jingle:apps:rtp:rtp-hdrext:0');
82 79
 
83
-        disco.addFeature('urn:ietf:rfc:5761'); // rtcp-mux
84
-        disco.addFeature('urn:ietf:rfc:5888'); // a=group, e.g. bundle
80
+        this.caps.addFeature('urn:ietf:rfc:5761'); // rtcp-mux
81
+        this.caps.addFeature('urn:ietf:rfc:5888'); // a=group, e.g. bundle
85 82
 
86
-        //disco.addFeature('urn:ietf:rfc:5576'); // a=ssrc
83
+        //this.caps.addFeature('urn:ietf:rfc:5576'); // a=ssrc
87 84
 
88 85
         // Enable Lipsync ?
89 86
         if (RTCBrowserType.isChrome() && false !== this.options.enableLipSync) {
90 87
             logger.info("Lip-sync enabled !");
91
-            disco.addFeature('http://jitsi.org/meet/lipsync');
88
+            this.caps.addFeature('http://jitsi.org/meet/lipsync');
89
+        }
90
+
91
+        if(this.connection.rayo) {
92
+            this.caps.addFeature('urn:xmpp:rayo:client:1');
92 93
         }
93 94
     }
94 95
 
@@ -371,7 +372,7 @@ export default class XMPP extends Listenable {
371 372
         initEmuc(this);
372 373
         initJingle(this, this.eventEmitter);
373 374
         initStropheUtil();
374
-        initPing(this, this.eventEmitter);
375
+        initPing(this);
375 376
         initRayo();
376 377
         initStropheLogger();
377 378
     }

+ 8
- 0
service/xmpp/XMPPEvents.js 查看文件

@@ -43,6 +43,14 @@ var XMPPEvents = {
43 43
     // Designates an event indicating that the display name of a participant
44 44
     // has changed.
45 45
     DISPLAY_NAME_CHANGED: "xmpp.display_name_changed",
46
+    /**
47
+     * Chat room instance have been added to Strophe.emuc plugin.
48
+     */
49
+    EMUC_ROOM_ADDED: "xmpp.emuc_room_added",
50
+    /**
51
+     * Chat room instance have been removed from Strophe.emuc plugin.
52
+     */
53
+    EMUC_ROOM_REMOVED: "xmpp.emuc_room_removed",
46 54
     ETHERPAD: "xmpp.etherpad",
47 55
     FOCUS_DISCONNECTED: 'xmpp.focus_disconnected',
48 56
     FOCUS_LEFT: "xmpp.focus_left",

正在加载...
取消
保存