Browse Source

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

of forcing one or the other in automated tests).
j8
Boris Grozev 10 years ago
parent
commit
62d3b749bb
4 changed files with 117 additions and 44 deletions
  1. 5
    0
      config.js
  2. 1
    1
      index.html
  3. 48
    2
      modules/xmpp/JingleSessionPC.js
  4. 63
    41
      modules/xmpp/SDP.js

+ 5
- 0
config.js View File

@@ -43,6 +43,11 @@ var config = {
43 43
     // The URL to the Firefox extension for desktop sharing.
44 44
     desktopSharingFirefoxExtensionURL: null,
45 45
 
46
+    // Disables ICE/UDP by filtering out local and remote UDP candidates in signalling.
47
+    webrtcIceUdpDisable: false,
48
+    // Disables ICE/TCP by filtering out local and remote TCP candidates in signalling.
49
+    webrtcIceTcpDisable: false,
50
+
46 51
     openSctp: true, // Toggle to enable/disable SCTP channels
47 52
     disableStats: false,
48 53
     disableAudioLevels: false,

+ 1
- 1
index.html View File

@@ -11,7 +11,7 @@
11 11
     <meta itemprop="image" content="/images/jitsilogo.png"/>
12 12
     <script src="https://api.callstats.io/static/callstats.min.js"></script>
13 13
     <script src="libs/jquery-2.1.1.min.js"></script>
14
-    <script src="config.js?v=13"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
14
+    <script src="config.js?v=14"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
15 15
     <script src="libs/strophe/strophe.min.js?v=2"></script>
16 16
     <script src="libs/strophe/strophe.disco.min.js?v=1"></script>
17 17
     <script src="libs/strophe/strophe.caps.jsonly.min.js?v=1"></script>

+ 48
- 2
modules/xmpp/JingleSessionPC.js View File

@@ -56,6 +56,7 @@ function JingleSessionPC(me, sid, connection, service, eventEmitter) {
56 56
     // stable and the ice connection state is connected.
57 57
     this.modifySourcesQueue.pause();
58 58
 }
59
+//XXX this is badly broken...
59 60
 JingleSessionPC.prototype = JingleSession.prototype;
60 61
 JingleSessionPC.prototype.constructor = JingleSessionPC;
61 62
 
@@ -95,6 +96,15 @@ JingleSessionPC.prototype.doInitialize = function () {
95 96
             this);
96 97
 
97 98
     this.peerconnection.onicecandidate = function (event) {
99
+        var protocol;
100
+        if (event && event.candidate) {
101
+            protocol = (typeof event.candidate.protocol === 'string')
102
+                ? event.candidate.protocol.toLowerCase() : '';
103
+            if ((config.webrtcIceTcpDisable && protocol == 'tcp') ||
104
+                (config.webrtcIceUdpDisable && protocol == 'udp')) {
105
+                return;
106
+            }
107
+        }
98 108
         self.sendIceCandidate(event.candidate);
99 109
     };
100 110
     this.peerconnection.onaddstream = function (event) {
@@ -229,6 +239,12 @@ JingleSessionPC.prototype.accept = function () {
229 239
         pranswer.sdp = pranswer.sdp.replace('a=inactive', 'a=sendrecv');
230 240
     }
231 241
     var prsdp = new SDP(pranswer.sdp);
242
+    if (config.webrtcIceTcpDisable) {
243
+        prsdp.removeTcpCandidates = true;
244
+    }
245
+    if (config.webrtcIceUdpDisable) {
246
+        prsdp.removeUdpCandidates = true;
247
+    }
232 248
     var accept = $iq({to: this.peerjid,
233 249
         type: 'set'})
234 250
         .c('jingle', {xmlns: 'urn:xmpp:jingle:1',
@@ -337,6 +353,12 @@ JingleSessionPC.prototype.sendIceCandidate = function (candidate) {
337 353
                     initiator: this.initiator,
338 354
                     sid: this.sid});
339 355
             this.localSDP = new SDP(this.peerconnection.localDescription.sdp);
356
+            if (config.webrtcIceTcpDisable) {
357
+                this.localSDP.removeTcpCandidates = true;
358
+            }
359
+            if (config.webrtcIceUdpDisable) {
360
+                this.localSDP.removeUdpCandidates = true;
361
+            }
340 362
             var sendJingle = function (ssrc) {
341 363
                 if(!ssrc)
342 364
                     ssrc = {};
@@ -533,8 +555,14 @@ JingleSessionPC.prototype.getSsrcOwner = function (ssrc) {
533 555
 };
534 556
 
535 557
 JingleSessionPC.prototype.setRemoteDescription = function (elem, desctype) {
536
-    //console.log('setting remote description... ', desctype);
537 558
     this.remoteSDP = new SDP('');
559
+    if (config.webrtcIceTcpDisable) {
560
+        this.remoteSDP.removeTcpCandidates = true;
561
+    }
562
+    if (config.webrtcIceUdpDisable) {
563
+        this.remoteSDP.removeUdpCandidates = true;
564
+    }
565
+
538 566
     this.remoteSDP.fromJingle(elem);
539 567
     this.readSsrcInfo($(elem).find(">content"));
540 568
     if (this.peerconnection.remoteDescription !== null) {
@@ -577,6 +605,10 @@ JingleSessionPC.prototype.setRemoteDescription = function (elem, desctype) {
577 605
     );
578 606
 };
579 607
 
608
+/**
609
+ * Adds remote ICE candidates to this Jingle session.
610
+ * @param elem An array of Jingle "content" elements?
611
+ */
580 612
 JingleSessionPC.prototype.addIceCandidate = function (elem) {
581 613
     var self = this;
582 614
     if (this.peerconnection.signalingState == 'closed') {
@@ -587,7 +619,7 @@ JingleSessionPC.prototype.addIceCandidate = function (elem) {
587 619
         // create a PRANSWER for setRemoteDescription
588 620
         if (!this.remoteSDP) {
589 621
             var cobbled = 'v=0\r\n' +
590
-                'o=- ' + '1923518516' + ' 2 IN IP4 0.0.0.0\r\n' +// FIXME
622
+                'o=- 1923518516 2 IN IP4 0.0.0.0\r\n' +// FIXME
591 623
                 's=-\r\n' +
592 624
                 't=0 0\r\n';
593 625
             // first, take some things from the local description
@@ -672,6 +704,14 @@ JingleSessionPC.prototype.addIceCandidate = function (elem) {
672 704
         // TODO: check ice-pwd and ice-ufrag?
673 705
         $(this).find('transport>candidate').each(function () {
674 706
             var line, candidate;
707
+            var protocol = this.getAttribute('protocol');
708
+            protocol =
709
+                (typeof protocol === 'string') ? protocol.toLowerCase() : '';
710
+            if ((config.webrtcIceTcpDisable && protocol == 'tcp') ||
711
+                (config.webrtcIceUdpDisable && protocol == 'udp')) {
712
+                return;
713
+            }
714
+
675 715
             line = SDPUtil.candidateFromJingle(this);
676 716
             candidate = new RTCIceCandidate({sdpMLineIndex: idx,
677 717
                 sdpMid: name,
@@ -724,6 +764,12 @@ JingleSessionPC.prototype.createdAnswer = function (sdp, provisional) {
724 764
                         initiator: self.initiator,
725 765
                         responder: self.responder,
726 766
                         sid: self.sid });
767
+                if (config.webrtcIceTcpDisable) {
768
+                    self.localSDP.removeTcpCandidates = true;
769
+                }
770
+                if (config.webrtcIceUdpDisable) {
771
+                    self.localSDP.removeUdpCandidates = true;
772
+                }
727 773
                 self.localSDP.toJingle(
728 774
                     accept,
729 775
                     self.initiator == self.me ? 'initiator' : 'responder',

+ 63
- 41
modules/xmpp/SDP.js View File

@@ -4,6 +4,18 @@ var SDPUtil = require("./SDPUtil");
4 4
 
5 5
 // SDP STUFF
6 6
 function SDP(sdp) {
7
+    /**
8
+     * Whether or not to remove TCP ice candidates when translating from/to jingle.
9
+     * @type {boolean}
10
+     */
11
+    this.removeTcpCandidates = false;
12
+
13
+    /**
14
+     * Whether or not to remove UDP ice candidates when translating from/to jingle.
15
+     * @type {boolean}
16
+     */
17
+    this.removeUdpCandidates = false;
18
+
7 19
     this.media = sdp.split('\r\nm=');
8 20
     for (var i = 1; i < this.media.length; i++) {
9 21
         this.media[i] = 'm=' + this.media[i];
@@ -14,6 +26,7 @@ function SDP(sdp) {
14 26
     this.session = this.media.shift() + '\r\n';
15 27
     this.raw = this.session + this.media.join('');
16 28
 }
29
+
17 30
 /**
18 31
  * Returns map of MediaChannel mapped per channel idx.
19 32
  */
@@ -63,18 +76,16 @@ SDP.prototype.getMediaSsrcMap = function() {
63 76
  */
64 77
 SDP.prototype.containsSSRC = function(ssrc) {
65 78
     var medias = this.getMediaSsrcMap();
66
-    var contains = false;
67 79
     Object.keys(medias).forEach(function(mediaindex){
68 80
         var media = medias[mediaindex];
69 81
         //console.log("Check", channel, ssrc);
70 82
         if(Object.keys(media.ssrcs).indexOf(ssrc) != -1){
71
-            contains = true;
83
+            return true;
72 84
         }
73 85
     });
74
-    return contains;
86
+    return false;
75 87
 };
76 88
 
77
-
78 89
 // remove iSAC and CN from SDP
79 90
 SDP.prototype.mangle = function () {
80 91
     var i, j, mline, lines, rtpmap, newdesc;
@@ -129,8 +140,7 @@ SDP.prototype.removeMediaLines = function(mediaindex, prefix) {
129 140
 // add content's to a jingle element
130 141
 SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
131 142
 //    console.log("SSRC" + ssrcs["audio"] + " - " + ssrcs["video"]);
132
-    var i, j, k, mline, ssrc, rtpmap, tmp, line, lines;
133
-    var self = this;
143
+    var i, j, k, mline, ssrc, rtpmap, tmp, lines;
134 144
     // new bundle plan
135 145
     if (SDPUtil.find_line(this.session, 'a=group:')) {
136 146
         lines = SDPUtil.find_lines(this.session, 'a=group:');
@@ -155,12 +165,11 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
155 165
         if (SDPUtil.find_line(this.media[i], 'a=ssrc:')) {
156 166
             ssrc = SDPUtil.find_line(this.media[i], 'a=ssrc:').substring(7).split(' ')[0]; // take the first
157 167
         } else {
158
-            if(ssrcs && ssrcs[mline.media])
159
-            {
168
+            if(ssrcs && ssrcs[mline.media]) {
160 169
                 ssrc = ssrcs[mline.media];
161
-            }
162
-            else
170
+            } else {
163 171
                 ssrc = false;
172
+            }
164 173
         }
165 174
 
166 175
         elem.c('content', {creator: thecreator, name: mline.media});
@@ -170,8 +179,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
170 179
             elem.attrs({ name: mid });
171 180
         }
172 181
 
173
-        if (SDPUtil.find_line(this.media[i], 'a=rtpmap:').length)
174
-        {
182
+        if (SDPUtil.find_line(this.media[i], 'a=rtpmap:').length) {
175 183
             elem.c('description',
176 184
                 {xmlns: 'urn:xmpp:jingle:apps:rtp:1',
177 185
                     media: mline.media });
@@ -188,7 +196,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
188 196
                         elem.c('parameter', tmp[k]).up();
189 197
                     }
190 198
                 }
191
-                this.RtcpFbToJingle(i, elem, mline.fmt[j]); // XEP-0293 -- map a=rtcp-fb
199
+                this.rtcpFbToJingle(i, elem, mline.fmt[j]); // XEP-0293 -- map a=rtcp-fb
192 200
 
193 201
                 elem.up();
194 202
             }
@@ -208,7 +216,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
208 216
                 var ssrclines = SDPUtil.find_lines(this.media[i], 'a=ssrc:');
209 217
                 if(ssrclines.length > 0) {
210 218
                     ssrclines.forEach(function (line) {
211
-                        idx = line.indexOf(' ');
219
+                        var idx = line.indexOf(' ');
212 220
                         var linessrc = line.substr(0, idx).substr(7);
213 221
                         if (linessrc != ssrc) {
214 222
                             elem.up();
@@ -229,9 +237,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
229 237
                         }
230 238
                         elem.up();
231 239
                     });
232
-                }
233
-                else
234
-                {
240
+                } else {
235 241
                     elem.up();
236 242
                     elem.c('source', { ssrc: ssrc, xmlns: 'urn:xmpp:jingle:apps:rtp:ssma:0' });
237 243
                     elem.c('parameter');
@@ -261,7 +267,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
261 267
                 // XEP-0339 handle ssrc-group attributes
262 268
                 var ssrc_group_lines = SDPUtil.find_lines(this.media[i], 'a=ssrc-group:');
263 269
                 ssrc_group_lines.forEach(function(line) {
264
-                    idx = line.indexOf(' ');
270
+                    var idx = line.indexOf(' ');
265 271
                     var semantics = line.substr(0, idx).substr(13);
266 272
                     var ssrcs = line.substr(14 + semantics.length).split(' ');
267 273
                     if (ssrcs.length) {
@@ -280,7 +286,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
280 286
             }
281 287
 
282 288
             // XEP-0293 -- map a=rtcp-fb:*
283
-            this.RtcpFbToJingle(i, elem, '*');
289
+            this.rtcpFbToJingle(i, elem, '*');
284 290
 
285 291
             // XEP-0294
286 292
             if (SDPUtil.find_line(this.media[i], 'a=extmap:')) {
@@ -314,7 +320,7 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
314 320
         }
315 321
 
316 322
         // map ice-ufrag/pwd, dtls fingerprint, candidates
317
-        this.TransportToJingle(i, elem);
323
+        this.transportToJingle(i, elem);
318 324
 
319 325
         if (SDPUtil.find_line(this.media[i], 'a=sendrecv', this.session)) {
320 326
             elem.attrs({senders: 'both'});
@@ -335,25 +341,24 @@ SDP.prototype.toJingle = function (elem, thecreator, ssrcs) {
335 341
     return elem;
336 342
 };
337 343
 
338
-SDP.prototype.TransportToJingle = function (mediaindex, elem) {
339
-    var i = mediaindex;
340
-    var tmp;
344
+SDP.prototype.transportToJingle = function (mediaindex, elem) {
345
+    var tmp, sctpmap, sctpAttrs, fingerprints;
341 346
     var self = this;
342 347
     elem.c('transport');
343 348
 
344 349
     // XEP-0343 DTLS/SCTP
345 350
     if (SDPUtil.find_line(this.media[mediaindex], 'a=sctpmap:').length)
346 351
     {
347
-        var sctpmap = SDPUtil.find_line(
348
-            this.media[i], 'a=sctpmap:', self.session);
352
+        sctpmap = SDPUtil.find_line(
353
+            this.media[mediaindex], 'a=sctpmap:', self.session);
349 354
         if (sctpmap)
350 355
         {
351
-            var sctpAttrs = SDPUtil.parse_sctpmap(sctpmap);
356
+            sctpAttrs = SDPUtil.parse_sctpmap(sctpmap);
352 357
             elem.c('sctpmap',
353 358
                 {
354 359
                     xmlns: 'urn:xmpp:jingle:transports:dtls-sctp:1',
355 360
                     number: sctpAttrs[0], /* SCTP port */
356
-                    protocol: sctpAttrs[1], /* protocol */
361
+                    protocol: sctpAttrs[1] /* protocol */
357 362
                 });
358 363
             // Optional stream count attribute
359 364
             if (sctpAttrs.length > 2)
@@ -362,7 +367,7 @@ SDP.prototype.TransportToJingle = function (mediaindex, elem) {
362 367
         }
363 368
     }
364 369
     // XEP-0320
365
-    var fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session);
370
+    fingerprints = SDPUtil.find_lines(this.media[mediaindex], 'a=fingerprint:', this.session);
366 371
     fingerprints.forEach(function(line) {
367 372
         tmp = SDPUtil.parse_fingerprint(line);
368 373
         tmp.xmlns = 'urn:xmpp:jingle:apps:dtls:0';
@@ -383,14 +388,22 @@ SDP.prototype.TransportToJingle = function (mediaindex, elem) {
383 388
         if (SDPUtil.find_line(this.media[mediaindex], 'a=candidate:', this.session)) { // add any a=candidate lines
384 389
             var lines = SDPUtil.find_lines(this.media[mediaindex], 'a=candidate:', this.session);
385 390
             lines.forEach(function (line) {
386
-                elem.c('candidate', SDPUtil.candidateToJingle(line)).up();
391
+                var candidate = SDPUtil.candidateToJingle(line);
392
+                var protocol = (candidate &&
393
+                        typeof candidate.protocol === 'string')
394
+                    ? candidate.protocol.toLowerCase() : '';
395
+                if ((self.removeTcpCandidates && protocol === 'tcp') ||
396
+                    (self.removeUdpCandidates && protocol === 'udp')) {
397
+                    return;
398
+                }
399
+                elem.c('candidate', candidate).up();
387 400
             });
388 401
         }
389 402
     }
390 403
     elem.up(); // end of transport
391 404
 };
392 405
 
393
-SDP.prototype.RtcpFbToJingle = function (mediaindex, elem, payloadtype) { // XEP-0293
406
+SDP.prototype.rtcpFbToJingle = function (mediaindex, elem, payloadtype) { // XEP-0293
394 407
     var lines = SDPUtil.find_lines(this.media[mediaindex], 'a=rtcp-fb:' + payloadtype);
395 408
     lines.forEach(function (line) {
396 409
         var tmp = SDPUtil.parse_rtcpfb(line);
@@ -407,7 +420,7 @@ SDP.prototype.RtcpFbToJingle = function (mediaindex, elem, payloadtype) { // XEP
407 420
     });
408 421
 };
409 422
 
410
-SDP.prototype.RtcpFbFromJingle = function (elem, payloadtype) { // XEP-0293
423
+SDP.prototype.rtcpFbFromJingle = function (elem, payloadtype) { // XEP-0293
411 424
     var media = '';
412 425
     var tmp = elem.find('>rtcp-fb-trr-int[xmlns="urn:xmpp:jingle:apps:rtp:rtcp-fb:0"]');
413 426
     if (tmp.length) {
@@ -434,7 +447,7 @@ SDP.prototype.RtcpFbFromJingle = function (elem, payloadtype) { // XEP-0293
434 447
 SDP.prototype.fromJingle = function (jingle) {
435 448
     var self = this;
436 449
     this.raw = 'v=0\r\n' +
437
-        'o=- ' + '1923518516' + ' 2 IN IP4 0.0.0.0\r\n' +// FIXME
450
+        'o=- 1923518516 2 IN IP4 0.0.0.0\r\n' +// FIXME
438 451
         's=-\r\n' +
439 452
         't=0 0\r\n';
440 453
     // http://tools.ietf.org/html/draft-ietf-mmusic-sdp-bundle-negotiation-04#section-8
@@ -490,14 +503,11 @@ SDP.prototype.jingle2media = function (content) {
490 503
     } else {
491 504
         tmp.proto = 'RTP/AVPF';
492 505
     }
493
-    if (!sctp.length)
494
-    {
506
+    if (!sctp.length) {
495 507
         tmp.fmt = desc.find('payload-type').map(
496 508
             function () { return this.getAttribute('id'); }).get();
497 509
         media += SDPUtil.build_mline(tmp) + '\r\n';
498
-    }
499
-    else
500
-    {
510
+    } else {
501 511
         media += 'm=application 1 DTLS/SCTP ' + sctp.attr('number') + '\r\n';
502 512
         media += 'a=sctpmap:' + sctp.attr('number') +
503 513
             ' ' + sctp.attr('protocol');
@@ -568,15 +578,19 @@ SDP.prototype.jingle2media = function (content) {
568 578
         media += SDPUtil.build_rtpmap(this) + '\r\n';
569 579
         if ($(this).find('>parameter').length) {
570 580
             media += 'a=fmtp:' + this.getAttribute('id') + ' ';
571
-            media += $(this).find('parameter').map(function () { return (this.getAttribute('name') ? (this.getAttribute('name') + '=') : '') + this.getAttribute('value'); }).get().join('; ');
581
+            media += $(this).find('parameter').map(function () {
582
+                return (this.getAttribute('name')
583
+                        ? (this.getAttribute('name') + '=') : '') +
584
+                    this.getAttribute('value');
585
+            }).get().join('; ');
572 586
             media += '\r\n';
573 587
         }
574 588
         // xep-0293
575
-        media += self.RtcpFbFromJingle($(this), this.getAttribute('id'));
589
+        media += self.rtcpFbFromJingle($(this), this.getAttribute('id'));
576 590
     });
577 591
 
578 592
     // xep-0293
579
-    media += self.RtcpFbFromJingle(desc, '*');
593
+    media += self.rtcpFbFromJingle(desc, '*');
580 594
 
581 595
     // xep-0294
582 596
     tmp = desc.find('>rtp-hdrext[xmlns="urn:xmpp:jingle:apps:rtp:rtp-hdrext:0"]');
@@ -585,11 +599,19 @@ SDP.prototype.jingle2media = function (content) {
585 599
     });
586 600
 
587 601
     content.find('>transport[xmlns="urn:xmpp:jingle:transports:ice-udp:1"]>candidate').each(function () {
602
+        var protocol = this.getAttribute('protocol');
603
+        protocol = (typeof protocol === 'string') ? protocol.toLowerCase(): '';
604
+
605
+        if ((self.removeTcpCandidates && protocol === 'tcp') ||
606
+            (self.removeUdpCandidates && protocol === 'udp')) {
607
+            return;
608
+        }
609
+
588 610
         media += SDPUtil.candidateFromJingle(this);
589 611
     });
590 612
 
591 613
     // XEP-0339 handle ssrc-group attributes
592
-    tmp = content.find('description>ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
614
+    content.find('description>ssrc-group[xmlns="urn:xmpp:jingle:apps:rtp:ssma:0"]').each(function() {
593 615
         var semantics = this.getAttribute('semantics');
594 616
         var ssrcs = $(this).find('>source').map(function() {
595 617
             return this.getAttribute('ssrc');

Loading…
Cancel
Save