Adds config options to filter out TCP or UDP candidates (for the purpose

of forcing one or the other in automated tests).
This commit is contained in:
Boris Grozev 2015-09-21 11:28:49 -05:00
parent ad38268cbd
commit 68624b3427
2 changed files with 114 additions and 41 deletions

View File

@ -46,6 +46,9 @@ function JingleSessionPC(me, sid, connection, service) {
this.ssrcOwners = {};
this.ssrcVideoTypes = {};
this.webrtcIceUdpDisable = !!this.service.options.webrtcIceUdpDisable;
this.webrtcIceTcpDisable = !!this.service.options.webrtcIceTcpDisable;
/**
* The indicator which determines whether the (local) video has been muted
* in response to a user command in contrast to an automatic decision made
@ -58,6 +61,7 @@ function JingleSessionPC(me, sid, connection, service) {
// stable and the ice connection state is connected.
this.modifySourcesQueue.pause();
}
//XXX this is badly broken...
JingleSessionPC.prototype = JingleSession.prototype;
JingleSessionPC.prototype.constructor = JingleSessionPC;
@ -97,6 +101,15 @@ JingleSessionPC.prototype.doInitialize = function () {
this);
this.peerconnection.onicecandidate = function (event) {
var protocol;
if (event && event.candidate) {
protocol = (typeof event.candidate.protocol === 'string')
? event.candidate.protocol.toLowerCase() : '';
if ((self.webrtcIceTcpDisable && protocol == 'tcp') ||
(self.webrtcIceUdpDisable && protocol == 'udp')) {
return;
}
}
self.sendIceCandidate(event.candidate);
};
this.peerconnection.onaddstream = function (event) {
@ -227,6 +240,12 @@ JingleSessionPC.prototype.accept = function () {
pranswer.sdp = pranswer.sdp.replace('a=inactive', 'a=sendrecv');
}
var prsdp = new SDP(pranswer.sdp);
if (self.webrtcIceTcpDisable) {
prsdp.removeTcpCandidates = true;
}
if (self.webrtcIceUdpDisable) {
prsdp.removeUdpCandidates = true;
}
var accept = $iq({to: this.peerjid,
type: 'set'})
.c('jingle', {xmlns: 'urn:xmpp:jingle:1',
@ -335,6 +354,12 @@ JingleSessionPC.prototype.sendIceCandidate = function (candidate) {
initiator: this.initiator,
sid: this.sid});
this.localSDP = new SDP(this.peerconnection.localDescription.sdp);
if (self.webrtcIceTcpDisable) {
this.localSDP.removeTcpCandidates = true;
}
if (self.webrtcIceUdpDisable) {
this.localSDP.removeUdpCandidates = true;
}
var sendJingle = function (ssrc) {
if(!ssrc)
ssrc = {};
@ -533,6 +558,13 @@ JingleSessionPC.prototype.getSsrcOwner = function (ssrc) {
JingleSessionPC.prototype.setRemoteDescription = function (elem, desctype) {
//logger.log('setting remote description... ', desctype);
this.remoteSDP = new SDP('');
if (self.webrtcIceTcpDisable) {
this.remoteSDP.removeTcpCandidates = true;
}
if (self.webrtcIceUdpDisable) {
this.remoteSDP.removeUdpCandidates = true;
}
this.remoteSDP.fromJingle(elem);
this.readSsrcInfo($(elem).find(">content"));
if (this.peerconnection.remoteDescription) {
@ -575,6 +607,10 @@ JingleSessionPC.prototype.setRemoteDescription = function (elem, desctype) {
);
};
/**
* Adds remote ICE candidates to this Jingle session.
* @param elem An array of Jingle "content" elements?
*/
JingleSessionPC.prototype.addIceCandidate = function (elem) {
var self = this;
if (this.peerconnection.signalingState == 'closed') {
@ -585,7 +621,7 @@ JingleSessionPC.prototype.addIceCandidate = function (elem) {
// create a PRANSWER for setRemoteDescription
if (!this.remoteSDP) {
var cobbled = 'v=0\r\n' +
'o=- ' + '1923518516' + ' 2 IN IP4 0.0.0.0\r\n' +// FIXME
'o=- 1923518516 2 IN IP4 0.0.0.0\r\n' +// FIXME
's=-\r\n' +
't=0 0\r\n';
// first, take some things from the local description
@ -670,6 +706,14 @@ JingleSessionPC.prototype.addIceCandidate = function (elem) {
// TODO: check ice-pwd and ice-ufrag?
$(this).find('transport>candidate').each(function () {
var line, candidate;
var protocol = this.getAttribute('protocol');
protocol =
(typeof protocol === 'string') ? protocol.toLowerCase() : '';
if ((self.webrtcIceTcpDisable && protocol == 'tcp') ||
(self.webrtcIceUdpDisable && protocol == 'udp')) {
return;
}
line = SDPUtil.candidateFromJingle(this);
candidate = new RTCIceCandidate({sdpMLineIndex: idx,
sdpMid: name,
@ -723,6 +767,12 @@ JingleSessionPC.prototype.createdAnswer = function (sdp, provisional) {
initiator: self.initiator,
responder: self.responder,
sid: self.sid });
if (self.webrtcIceTcpDisable) {
self.localSDP.removeTcpCandidates = true;
}
if (self.webrtcIceUdpDisable) {
self.localSDP.removeUdpCandidates = true;
}
self.localSDP.toJingle(
accept,
self.initiator == self.me ? 'initiator' : 'responder',

View File

@ -5,6 +5,18 @@ var SDPUtil = require("./SDPUtil");
// SDP STUFF
function SDP(sdp) {
/**
* Whether or not to remove TCP ice candidates when translating from/to jingle.
* @type {boolean}
*/
this.removeTcpCandidates = false;
/**
* Whether or not to remove UDP ice candidates when translating from/to jingle.
* @type {boolean}
*/
this.removeUdpCandidates = false;
this.media = sdp.split('\r\nm=');
for (var i = 1; i < this.media.length; i++) {
this.media[i] = 'm=' + this.media[i];
@ -15,6 +27,7 @@ function SDP(sdp) {
this.session = this.media.shift() + '\r\n';
this.raw = this.session + this.media.join('');
}
/**
* Returns map of MediaChannel mapped per channel idx.
*/
@ -64,18 +77,16 @@ SDP.prototype.getMediaSsrcMap = function() {
*/
SDP.prototype.containsSSRC = function(ssrc) {
var medias = this.getMediaSsrcMap();
var contains = false;
Object.keys(medias).forEach(function(mediaindex){
var media = medias[mediaindex];
//logger.log("Check", channel, ssrc);
if(Object.keys(media.ssrcs).indexOf(ssrc) != -1){
contains = true;
return true;
}
});
return contains;
return false;
};
// remove iSAC and CN from SDP
SDP.prototype.mangle = function () {
var i, j, mline, lines, rtpmap, newdesc;
@ -129,8 +140,8 @@ SDP.prototype.removeMediaLines = function(mediaindex, prefix) {
// add content's to a jingle element
SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
// logger.log("SSRC" + ssrcs["audio"] + " - " + ssrcs["video"]);
var i, j, k, mline, ssrc, rtpmap, tmp, line, lines;
var self = this;
var i, j, k, mline, ssrc, rtpmap, tmp, lines;
// new bundle plan
if (SDPUtil.find_line(this.session, 'a=group:')) {
lines = SDPUtil.find_lines(this.session, 'a=group:');
@ -155,12 +166,11 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
if (SDPUtil.find_line(this.media[i], 'a=ssrc:')) {
ssrc = SDPUtil.find_line(this.media[i], 'a=ssrc:').substring(7).split(' ')[0]; // take the first
} else {
if(ssrcs && ssrcs[mline.media])
{
if(ssrcs && ssrcs[mline.media]) {
ssrc = ssrcs[mline.media];
}
else
} else {
ssrc = false;
}
}
elem.c('content', {creator: thecreator, name: mline.media});
@ -170,8 +180,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
elem.attrs({ name: mid });
}
if (SDPUtil.find_line(this.media[i], 'a=rtpmap:').length)
{
if (SDPUtil.find_line(this.media[i], 'a=rtpmap:').length) {
elem.c('description',
{xmlns: 'urn:xmpp:jingle:apps:rtp:1',
media: mline.media });
@ -188,7 +197,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
elem.c('parameter', tmp[k]).up();
}
}
this.RtcpFbToJingle(i, elem, mline.fmt[j]); // XEP-0293 -- map a=rtcp-fb
this.rtcpFbToJingle(i, elem, mline.fmt[j]); // XEP-0293 -- map a=rtcp-fb
elem.up();
}
@ -208,7 +217,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
var ssrclines = SDPUtil.find_lines(this.media[i], 'a=ssrc:');
if(ssrclines.length > 0) {
ssrclines.forEach(function (line) {
idx = line.indexOf(' ');
var idx = line.indexOf(' ');
var linessrc = line.substr(0, idx).substr(7);
if (linessrc != ssrc) {
elem.up();
@ -229,9 +238,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
}
elem.up();
});
}
else
{
} else {
elem.up();
elem.c('source', { ssrc: ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
elem.c('parameter');
@ -265,7 +272,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
// XEP-0339 handle ssrc-group attributes
var ssrc_group_lines = SDPUtil.find_lines(this.media[i], 'a=ssrc-group:');
ssrc_group_lines.forEach(function(line) {
idx = line.indexOf(' ');
var idx = line.indexOf(' ');
var semantics = line.substr(0, idx).substr(13);
var ssrcs = line.substr(14 + semantics.length).split(' ');
if (ssrcs.length) {
@ -284,7 +291,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
}
// XEP-0293 -- map a=rtcp-fb:*
this.RtcpFbToJingle(i, elem, '*');
this.rtcpFbToJingle(i, elem, '*');
// XEP-0294
if (SDPUtil.find_line(this.media[i], 'a=extmap:')) {
@ -318,7 +325,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
}
// map ice-ufrag/pwd, dtls fingerprint, candidates
this.TransportToJingle(i, elem);
this.transportToJingle(i, elem);
if (SDPUtil.find_line(this.media[i], 'a=sendrecv', this.session)) {
elem.attrs({senders: 'both'});
@ -339,25 +346,24 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
return elem;
};
SDP.prototype.TransportToJingle = function (mediaindex, elem) {
var i = mediaindex;
var tmp;
SDP.prototype.transportToJingle = function (mediaindex, elem) {
var tmp, sctpmap, sctpAttrs, fingerprints;
var self = this;
elem.c('transport');
// XEP-0343 DTLS/SCTP
if (SDPUtil.find_line(this.media[mediaindex], 'a=sctpmap:').length)
{
var sctpmap = SDPUtil.find_line(
this.media[i], 'a=sctpmap:', self.session);
sctpmap = SDPUtil.find_line(
this.media[mediaindex], 'a=sctpmap:', self.session);
if (sctpmap)
{
var sctpAttrs = SDPUtil.parse_sctpmap(sctpmap);
sctpAttrs = SDPUtil.parse_sctpmap(sctpmap);
elem.c('sctpmap',
{
xmlns: 'urn:xmpp:jingle:transports:dtls-sctp:1',
number: sctpAttrs[0], /* SCTP port */
protocol: sctpAttrs[1], /* protocol */
protocol: sctpAttrs[1] /* protocol */
});
// Optional stream count attribute
if (sctpAttrs.length > 2)
@ -366,7 +372,7 @@ SDP.prototype.TransportToJingle = function (mediaindex, elem) {
}
}
// XEP-0320
var fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session);
fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session);
fingerprints.forEach(function(line) {
tmp = SDPUtil.parse_fingerprint(line);
tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0';
@ -387,14 +393,22 @@ SDP.prototype.TransportToJingle = function (mediaindex, elem) {
if (SDPUtil.find_line(this.media[mediaindex], 'a=candidate:', this.session)) { // add any a=candidate lines
var lines = SDPUtil.find_lines(this.media[mediaindex], 'a=candidate:', this.session);
lines.forEach(function (line) {
elem.c('candidate', SDPUtil.candidateToJingle(line)).up();
var candidate = SDPUtil.candidateToJingle(line);
var protocol = (candidate &&
typeof candidate.protocol === 'string')
? candidate.protocol.toLowerCase() : '';
if ((self.removeTcpCandidates && protocol === 'tcp') ||
(self.removeUdpCandidates && protocol === 'udp')) {
return;
}
elem.c('candidate', candidate).up();
});
}
}
elem.up(); // end of transport
}
SDP.prototype.RtcpFbToJingle = function (mediaindex, elem, payloadtype) { // XEP-0293
SDP.prototype.rtcpFbToJingle = function (mediaindex, elem, payloadtype) { // XEP-0293
var lines = SDPUtil.find_lines(this.media[mediaindex], 'a=rtcp-fb:' + payloadtype);
lines.forEach(function (line) {
var tmp = SDPUtil.parse_rtcpfb(line);
@ -411,7 +425,7 @@ SDP.prototype.RtcpFbToJingle = function (mediaindex, elem, payloadtype) { // XEP
});
};
SDP.prototype.RtcpFbFromJingle = function (elem, payloadtype) { // XEP-0293
SDP.prototype.rtcpFbFromJingle = function (elem, payloadtype) { // XEP-0293
var media = '';
var tmp = elem.find('>rtcp-fb-trr-int[xmlns="urn:xmpp:jingle:apps:rtp:rtcp-fb:0"]');
if (tmp.length) {
@ -438,7 +452,7 @@ SDP.prototype.RtcpFbFromJingle = function (elem, payloadtype) { // XEP-0293
SDP.prototype.fromJingle = function (jingle) {
var self = this;
this.raw = 'v=0\r\n' +
'o=- ' + '1923518516' + ' 2 IN IP4 0.0.0.0\r\n' +// FIXME
'o=- 1923518516 2 IN IP4 0.0.0.0\r\n' +// FIXME
's=-\r\n' +
't=0 0\r\n';
// http://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-04#section-8
@ -494,14 +508,11 @@ SDP.prototype.jingle2media = function (content) {
} else {
tmp.proto = 'RTP/AVPF';
}
if (!sctp.length)
{
if (!sctp.length) {
tmp.fmt = desc.find('payload-type').map(
function () { return this.getAttribute('id'); }).get();
media += SDPUtil.build_mline(tmp) + '\r\n';
}
else
{
} else {
media += 'm=application 1 DTLS/SCTP ' + sctp.attr('number') + '\r\n';
media += 'a=sctpmap:' + sctp.attr('number') +
' ' + sctp.attr('protocol');
@ -572,15 +583,19 @@ SDP.prototype.jingle2media = function (content) {
media += SDPUtil.build_rtpmap(this) + '\r\n';
if ($(this).find('>parameter').length) {
media += 'a=fmtp:' + this.getAttribute('id') + ' ';
media += $(this).find('parameter').map(function () { return (this.getAttribute('name') ? (this.getAttribute('name') + '=') : '') + this.getAttribute('value'); }).get().join('; ');
media += $(this).find('parameter').map(function () {
return (this.getAttribute('name')
? (this.getAttribute('name') + '=') : '') +
this.getAttribute('value');
}).get().join('; ');
media += '\r\n';
}
// xep-0293
media += self.RtcpFbFromJingle($(this), this.getAttribute('id'));
media += self.rtcpFbFromJingle($(this), this.getAttribute('id'));
});
// xep-0293
media += self.RtcpFbFromJingle(desc, '*');
media += self.rtcpFbFromJingle(desc, '*');
// xep-0294
tmp = desc.find('>rtp-hdrext[xmlns="urn:xmpp:jingle:apps:rtp:rtp-hdrext:0"]');
@ -589,11 +604,19 @@ SDP.prototype.jingle2media = function (content) {
});
content.find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]>candidate').each(function () {
var protocol = this.getAttribute('protocol');
protocol = (typeof protocol === 'string') ? protocol.toLowerCase(): '';
if ((self.removeTcpCandidates && protocol === 'tcp') ||
(self.removeUdpCandidates && protocol === 'udp')) {
return;
}
media += SDPUtil.candidateFromJingle(this);
});
// XEP-0339 handle ssrc-group attributes
tmp = content.find('description>ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
content.find('description>ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
var semantics = this.getAttribute('semantics');
var ssrcs = $(this).find('>source').map(function() {
return this.getAttribute('ssrc');