Adds support for bundle.

This commit is contained in:
Boris Grozev 2014-08-18 11:44:16 +03:00
parent 01811c15fe
commit 20b69ce5ca
2 changed files with 64 additions and 9 deletions

View File

@ -19,5 +19,6 @@ var config = {
//defaultSipNumber: '20669', //Default SIP number used in call dialog //defaultSipNumber: '20669', //Default SIP number used in call dialog
// channelLastN: -1, // The default value of the channel attribute last-n. // channelLastN: -1, // The default value of the channel attribute last-n.
// useRtcpMux: true, // useRtcpMux: true,
// useBundle: true,
enableRecording: false enableRecording: false
}; };

View File

@ -72,6 +72,7 @@ function ColibriFocus(connection, bridgejid) {
this.media = ['audio', 'video']; this.media = ['audio', 'video'];
this.connection.jingle.sessions[this.sid] = this; this.connection.jingle.sessions[this.sid] = this;
this.bundledTransports = {};
this.mychannel = []; this.mychannel = [];
this.channels = []; this.channels = [];
this.remotessrc = {}; this.remotessrc = {};
@ -296,13 +297,20 @@ ColibriFocus.prototype._makeConference = function () {
elem.c(elemName, elemAttrs); elem.c(elemName, elemAttrs);
elem.attrs({ endpoint: self.myMucResource }); elem.attrs({ endpoint: self.myMucResource });
if (config.useBundle) {
elem.attrs({ 'channel-bundle-id': self.myMucResource });
}
elem.up();// end of channel/sctpconnection elem.up();// end of channel/sctpconnection
for (var j = 0; j < self.peers.length; j++) { for (var j = 0; j < self.peers.length; j++) {
var peer = self.peers[j]; var peer = self.peers[j];
var peerEndpoint = peer.substr(1 + peer.lastIndexOf('/'));
elem.c(elemName, elemAttrs); elem.c(elemName, elemAttrs);
elem.attrs({ endpoint: peer.substr(1 + peer.lastIndexOf('/')) }); elem.attrs({ endpoint: peerEndpoint });
if (config.useBundle) {
elem.attrs({ 'channel-bundle-id': peerEndpoint });
}
elem.up(); // end of channel/sctpconnection elem.up(); // end of channel/sctpconnection
} }
elem.up(); // end of content elem.up(); // end of content
@ -353,7 +361,7 @@ ColibriFocus.prototype._makeConference = function () {
); );
}; };
// callback when a conference was created // callback when a colibri conference was created
ColibriFocus.prototype.createdConference = function (result) { ColibriFocus.prototype.createdConference = function (result) {
console.log('created a conference on the bridge'); console.log('created a conference on the bridge');
var self = this; var self = this;
@ -379,6 +387,14 @@ ColibriFocus.prototype.createdConference = function (result) {
} }
} }
// save the 'transport' elements from 'channel-bundle'-s
var channelBundles = $(result).find('>conference>channel-bundle');
for (var i = 0; i < channelBundles.length; i++)
{
var endpointId = $(channelBundles[i]).attr('id');
this.bundledTransports[endpointId] = $(channelBundles[i]).find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]');
}
console.log('remote channels', this.channels); console.log('remote channels', this.channels);
// Notify that the focus has created the conference on the bridge // Notify that the focus has created the conference on the bridge
@ -390,6 +406,11 @@ ColibriFocus.prototype.createdConference = function (result) {
's=-\r\n' + 's=-\r\n' +
't=0 0\r\n' + 't=0 0\r\n' +
/* Audio */ /* Audio */
(config.useBundle
? ('a=group:BUNDLE audio video' +
(config.openSctp ? ' data' : '') +
'\r\n')
: '') +
'm=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126\r\n' + 'm=audio 1 RTP/SAVPF 111 103 104 0 8 106 105 13 126\r\n' +
'c=IN IP4 0.0.0.0\r\n' + 'c=IN IP4 0.0.0.0\r\n' +
'a=rtcp:1 IN IP4 0.0.0.0\r\n' + 'a=rtcp:1 IN IP4 0.0.0.0\r\n' +
@ -490,7 +511,13 @@ ColibriFocus.prototype.createdConference = function (result) {
} }
// FIXME: should take code from .fromJingle // FIXME: should take code from .fromJingle
tmp = $(this.mychannel[channel]).find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]'); var channelBundleId = $(this.mychannel[channel]).attr('channel-bundle-id');
if (typeof channelBundleId != 'undefined') {
tmp = this.bundledTransports[channelBundleId];
} else {
tmp = $(this.mychannel[channel]).find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]');
}
if (tmp.length) { if (tmp.length) {
bridgeSDP.media[channel] += 'a=ice-ufrag:' + tmp.attr('ufrag') + '\r\n'; bridgeSDP.media[channel] += 'a=ice-ufrag:' + tmp.attr('ufrag') + '\r\n';
bridgeSDP.media[channel] += 'a=ice-pwd:' + tmp.attr('pwd') + '\r\n'; bridgeSDP.media[channel] += 'a=ice-pwd:' + tmp.attr('pwd') + '\r\n';
@ -514,7 +541,7 @@ ColibriFocus.prototype.createdConference = function (result) {
function (answer) { function (answer) {
self.peerconnection.setLocalDescription(answer, self.peerconnection.setLocalDescription(answer,
function () { function () {
console.log('setLocalDescription succeded.'); console.log('setLocalDescription succeeded.');
// make sure our presence is updated // make sure our presence is updated
$(document).trigger('setLocalDescription.jingle', [self.sid]); $(document).trigger('setLocalDescription.jingle', [self.sid]);
var elem = $iq({to: self.bridgejid, type: 'get'}); var elem = $iq({to: self.bridgejid, type: 'get'});
@ -570,7 +597,7 @@ ColibriFocus.prototype.createdConference = function (result) {
}, },
function (error) { function (error) {
console.error( console.error(
"ERROR setLocalDescription succeded", "ERROR sending colibri message",
error, elem); error, elem);
} }
); );
@ -616,7 +643,9 @@ ColibriFocus.prototype.initiate = function (peer, isInitiator) {
var localSDP = new SDP(this.peerconnection.localDescription.sdp); var localSDP = new SDP(this.peerconnection.localDescription.sdp);
// throw away stuff we don't want // throw away stuff we don't want
// not needed with static offer // not needed with static offer
sdp.removeSessionLines('a=group:'); if (!config.useBundle) {
sdp.removeSessionLines('a=group:');
}
sdp.removeSessionLines('a=msid-semantic:'); // FIXME: not mapped over jingle anyway... sdp.removeSessionLines('a=msid-semantic:'); // FIXME: not mapped over jingle anyway...
for (var i = 0; i < sdp.media.length; i++) { for (var i = 0; i < sdp.media.length; i++) {
if (!config.useRtcpMux){ if (!config.useRtcpMux){
@ -670,7 +699,14 @@ ColibriFocus.prototype.initiate = function (peer, isInitiator) {
sdp.media[j] += 'a=ssrc:' + '3735928559' + ' ' + 'mslabel:mixedmslabel' + '\r\n'; sdp.media[j] += 'a=ssrc:' + '3735928559' + ' ' + 'mslabel:mixedmslabel' + '\r\n';
} }
tmp = chan.find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]'); // In the case of bundle, we add each candidate to all m= lines/jingle contents,
// just as chrome does
if (config.useBundle){
tmp = this.bundledTransports[chan.attr('channel-bundle-id')];
} else {
tmp = chan.find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]');
}
if (tmp.length) { if (tmp.length) {
if (tmp.attr('ufrag')) if (tmp.attr('ufrag'))
sdp.media[j] += 'a=ice-ufrag:' + tmp.attr('ufrag') + '\r\n'; sdp.media[j] += 'a=ice-ufrag:' + tmp.attr('ufrag') + '\r\n';
@ -757,12 +793,17 @@ ColibriFocus.prototype.addNewParticipant = function (peer) {
localSDP.media.forEach(function (media, channel) { localSDP.media.forEach(function (media, channel) {
var name = SDPUtil.parse_mid(SDPUtil.find_line(media, 'a=mid:')); var name = SDPUtil.parse_mid(SDPUtil.find_line(media, 'a=mid:'));
var elemName; var elemName;
var endpointId = peer.substr(1 + peer.lastIndexOf('/'));
var elemAttrs var elemAttrs
= { = {
initiator: 'true', initiator: 'true',
expire: self.channelExpire, expire: self.channelExpire,
endpoint: peer.substr(1 + peer.lastIndexOf('/')) endpoint: endpointId
}; };
if (config.useBundle) {
elemAttrs['channel-bundle-id'] = endpointId;
}
if ('data' == name) if ('data' == name)
{ {
@ -785,7 +826,8 @@ ColibriFocus.prototype.addNewParticipant = function (peer) {
this.connection.sendIQ(elem, this.connection.sendIQ(elem,
function (result) { function (result) {
var contents = $(result).find('>conference>content').get(); var contents = $(result).find('>conference>content').get();
for (var i = 0; i < contents.length; i++) { var i;
for (i = 0; i < contents.length; i++) {
var channelXml = $(contents[i]).find('>channel'); var channelXml = $(contents[i]).find('>channel');
if (channelXml.length) if (channelXml.length)
{ {
@ -797,6 +839,12 @@ ColibriFocus.prototype.addNewParticipant = function (peer) {
} }
self.channels[index][i] = tmp[0]; self.channels[index][i] = tmp[0];
} }
var channelBundles = $(result).find('>conference>channel-bundle');
for (i = 0; i < channelBundles.length; i++)
{
var endpointId = $(channelBundles[i]).attr('id');
self.bundledTransports[endpointId] = $(channelBundles[i]).find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]');
}
self.initiate(peer, true); self.initiate(peer, true);
}, },
function (error) { function (error) {
@ -1023,6 +1071,12 @@ ColibriFocus.prototype.addIceCandidate = function (session, elem) {
$(elem).each(function () { $(elem).each(function () {
var name = $(this).attr('name'); var name = $(this).attr('name');
// If we are using bundle, audio/video/data channel will have the same candidates, so only send them for
// the audio channel.
if (config.useBundle && name !== 'audio') {
return;
}
var channel = name == 'audio' ? 0 : 1; // FIXME: search mlineindex in localdesc var channel = name == 'audio' ? 0 : 1; // FIXME: search mlineindex in localdesc
if (name != 'audio' && name != 'video') if (name != 'audio' && name != 'video')
channel = 2; // name == 'data' channel = 2; // name == 'data'