tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_peerConnection_gatherWithSetConfiguration.html (21224B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <script type="application/javascript" src="pc.js"></script>
      5  <script type="application/javascript" src="iceTestUtils.js"></script>
      6  <script type="application/javascript" src="helpers_from_wpt/sdp.js"></script></head>
      7 <body>
      8 <pre id="test">
      9 <script type="application/javascript">
     10  createHTML({
     11    bug: "1253706",
     12    title: "Test ICE gathering when setConfiguration is used to change the ICE config"
     13  });
     14 
     15  const tests = [
     16    async function baselineV4Cases() {
     17      await checkSrflx([{urls:[`stun:${turnAddressV4}`]}]);
     18      await checkRelayUdp([{urls:[`turn:${turnAddressV4}`], username, credential}]);
     19      await checkRelayTcp([{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]);
     20      await checkRelayUdpTcp([{urls:[`turn:${turnAddressV4}`, `turn:${turnAddressV4}?transport=tcp`], username, credential}]);
     21      await checkNoSrflx();
     22      await checkNoRelay();
     23    },
     24 
     25    async function addStunServerBeforeOffer() {
     26      const pc = new RTCPeerConnection();
     27      try {
     28        pc.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
     29        const candidates = await gatherWithTimeout(pc, 32000, `just a stun server`);
     30        ok(candidates.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
     31        ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
     32      } finally {
     33        pc.close();
     34      }
     35    },
     36 
     37    async function addTurnServerBeforeOffer() {
     38      const pc = new RTCPeerConnection();
     39      try {
     40        pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
     41        const candidates = await gatherWithTimeout(pc, 32000, `a turn (udp) server`);
     42        ok(candidates.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
     43        ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
     44      } finally {
     45        pc.close();
     46      }
     47    },
     48 
     49    async function addTurnTcpServerBeforeOffer() {
     50      const pc = new RTCPeerConnection();
     51      try {
     52        pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
     53        const candidates = await gatherWithTimeout(pc, 32000, `a turn (tcp) server`);
     54        ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
     55        ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
     56      } finally {
     57        pc.close();
     58      }
     59    },
     60 
     61    async function addStunServerAfterOffer() {
     62      const pc = new RTCPeerConnection();
     63      try {
     64        const candidates1 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
     65        ok(!candidates1.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
     66        ok(!candidates1.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
     67        await pc.setLocalDescription({type: "rollback"});
     68 
     69        pc.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
     70        const candidates2 = await gatherWithTimeout(pc, 32000, `just a stun server`);
     71        ok(candidates2.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
     72        ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
     73      } finally {
     74        pc.close();
     75      }
     76    },
     77 
     78    async function addTurnServerAfterOffer() {
     79      const pc = new RTCPeerConnection();
     80      try {
     81        const candidates1 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
     82        ok(!candidates1.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
     83        ok(!candidates1.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
     84        await pc.setLocalDescription({type: "rollback"});
     85 
     86        pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
     87        const candidates2 = await gatherWithTimeout(pc, 32000, `a turn (udp) server`);
     88        ok(candidates2.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
     89        ok(candidates2.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
     90      } finally {
     91        pc.close();
     92      }
     93    },
     94 
     95    async function addTurnTcpServerAfterOffer() {
     96      const pc = new RTCPeerConnection();
     97      try {
     98        const candidates1 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
     99        ok(!candidates1.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
    100        ok(!candidates1.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    101        await pc.setLocalDescription({type: "rollback"});
    102 
    103        pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
    104        const candidates2 = await gatherWithTimeout(pc, 32000, `a turn (tcp) server`);
    105        ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should get no srflx candidates");
    106        ok(candidates2.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
    107      } finally {
    108        pc.close();
    109      }
    110    },
    111 
    112    async function removeStunServerBeforeOffer() {
    113      const pc = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    114      try {
    115        pc.setConfiguration({});
    116        const candidates = await gatherWithTimeout(pc, 32000, `no ICE servers`);
    117        ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
    118        ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    119      } finally {
    120        pc.close();
    121      }
    122    },
    123 
    124    async function removeTurnServerBeforeOffer() {
    125      const pc = new RTCPeerConnection({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
    126      try {
    127        pc.setConfiguration({});
    128        const candidates = await gatherWithTimeout(pc, 32000, `no ICE servers`);
    129        ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
    130        ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    131      } finally {
    132        pc.close();
    133      }
    134    },
    135 
    136    async function removeTurnTcpServerBeforeOffer() {
    137      const pc = new RTCPeerConnection({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
    138      try {
    139        pc.setConfiguration({});
    140        const candidates = await gatherWithTimeout(pc, 32000, `no ICE servers`);
    141        ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
    142        ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    143      } finally {
    144        pc.close();
    145      }
    146    },
    147 
    148    async function removeStunServerAfterOffer() {
    149      const pc = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    150      try {
    151        const candidates1 = await gatherWithTimeout(pc, 32000, `just a stun server`);
    152        ok(candidates1.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
    153        ok(!candidates1.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    154        await pc.setLocalDescription({type: "rollback"});
    155 
    156        pc.setConfiguration({});
    157        const candidates2 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
    158        ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
    159        ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    160      } finally {
    161        pc.close();
    162      }
    163    },
    164 
    165    async function removeTurnServerAfterOffer() {
    166      const pc = new RTCPeerConnection({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
    167      try {
    168        const candidates1 = await gatherWithTimeout(pc, 32000, `a turn (udp) server`);
    169        ok(candidates1.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
    170        ok(candidates1.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
    171        await pc.setLocalDescription({type: "rollback"});
    172 
    173        pc.setConfiguration({});
    174        const candidates2 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
    175        ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
    176        ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    177      } finally {
    178        pc.close();
    179      }
    180    },
    181 
    182    async function removeTurnTcpServerAfterOffer() {
    183      const pc = new RTCPeerConnection({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
    184      try {
    185        const candidates1 = await gatherWithTimeout(pc, 32000, `a turn (tcp) server`);
    186        ok(!candidates1.some(c => c.candidate.includes("srflx")), "Should get no srflx candidates");
    187        ok(candidates1.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
    188        await pc.setLocalDescription({type: "rollback"});
    189 
    190        pc.setConfiguration({});
    191        const candidates2 = await gatherWithTimeout(pc, 32000, `no ICE servers`);
    192        ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
    193        ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    194      } finally {
    195        pc.close();
    196      }
    197    },
    198 
    199    async function addStunServerAfterNegotiation() {
    200      const offerer = new RTCPeerConnection();
    201      const answerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    202      try {
    203        const candidatePromise = trickleIce(offerer);
    204        await connect(offerer, answerer, 32000, `no ICE servers`);
    205        const candidates = await candidatePromise;
    206        const ufrags = Array.from(new Set(candidates.map(c => c.usernameFragment)));
    207        is(ufrags.length, 1, "Should have one ufrag in candidate set");
    208 
    209        offerer.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    210        const candidates2 = await gatherWithTimeout(offerer, 32000, `just a stun server`);
    211        ok(candidates2.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
    212        ok(!candidates2.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    213        const ufrags2 = Array.from(new Set(candidates2.map(c => c.usernameFragment)));
    214        is(ufrags2.length, 1, "Should have one ufrag in candidate set");
    215        isnot(ufrags[0], ufrags2[0], "ufrag should change, because setConfiguration should have triggered an ICE restart");
    216      } finally {
    217        offerer.close();
    218        answerer.close();
    219      }
    220    },
    221 
    222    async function addTurnServerAfterNegotiation() {
    223      const offerer = new RTCPeerConnection();
    224      const answerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    225      try {
    226        const candidatePromise = trickleIce(offerer);
    227        await connect(offerer, answerer, 32000, `no ICE servers`);
    228        const candidates = await candidatePromise;
    229        const ufrags = Array.from(new Set(candidates.map(c => c.usernameFragment)));
    230        is(ufrags.length, 1, "Should have one ufrag in candidate set");
    231 
    232        offerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
    233        const candidates2 = await gatherWithTimeout(offerer, 32000, `a turn (udp) server`);
    234        ok(candidates2.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
    235        ok(candidates2.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
    236        const ufrags2 = Array.from(new Set(candidates2.map(c => c.usernameFragment)));
    237        is(ufrags2.length, 1, "Should have one ufrag in candidate set");
    238        isnot(ufrags[0], ufrags2[0], "ufrag should change, because setConfiguration should have triggered an ICE restart");
    239      } finally {
    240        offerer.close();
    241        answerer.close();
    242      }
    243    },
    244 
    245    async function addTurnTcpServerAfterNegotiation() {
    246      const offerer = new RTCPeerConnection();
    247      const answerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    248      try {
    249        const candidatePromise = trickleIce(offerer);
    250        await connect(offerer, answerer, 32000, `no ICE servers`);
    251        const candidates = await candidatePromise;
    252        const ufrags = Array.from(new Set(candidates.map(c => c.usernameFragment)));
    253        is(ufrags.length, 1, "Should have one ufrag in candidate set");
    254 
    255        offerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
    256        const candidates2 = await gatherWithTimeout(offerer, 32000, `a turn (tcp) server`);
    257        ok(!candidates2.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
    258        ok(candidates2.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
    259        const ufrags2 = Array.from(new Set(candidates2.map(c => c.usernameFragment)));
    260        is(ufrags2.length, 1, "Should have one ufrag in candidate set");
    261        isnot(ufrags[0], ufrags2[0], "ufrag should change, because setConfiguration should have triggered an ICE restart");
    262      } finally {
    263        offerer.close();
    264        answerer.close();
    265      }
    266    },
    267 
    268    async function addStunServerBeforeCreateAnswer() {
    269      const offerer = new RTCPeerConnection();
    270      const answerer = new RTCPeerConnection();
    271 
    272      try {
    273        await answerer.setRemoteDescription(await offerer.createOffer({offerToReceiveAudio: true}));
    274 
    275        answerer.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    276        const candidates = await gatherWithTimeout(answerer, 32000, `just a stun server`);
    277        ok(candidates.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
    278        ok(!candidates.some(c => c.candidate.includes("relay")), "Should not get any relay candidates");
    279      } finally {
    280        offerer.close();
    281        answerer.close();
    282      }
    283    },
    284 
    285    async function addTurnServerBeforeCreateAnswer() {
    286      const offerer = new RTCPeerConnection();
    287      const answerer = new RTCPeerConnection();
    288 
    289      try {
    290        await answerer.setRemoteDescription(await offerer.createOffer({offerToReceiveAudio: true}));
    291 
    292        answerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
    293        const candidates = await gatherWithTimeout(answerer, 32000, `a turn (udp) server`);
    294        ok(candidates.some(c => c.candidate.includes("srflx")), "Should get at least one srflx candidate");
    295        ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
    296      } finally {
    297        offerer.close();
    298        answerer.close();
    299      }
    300    },
    301 
    302    async function addTurnTcpServerBeforeCreateAnswer() {
    303      const offerer = new RTCPeerConnection();
    304      const answerer = new RTCPeerConnection();
    305 
    306      try {
    307        await answerer.setRemoteDescription(await offerer.createOffer({offerToReceiveAudio: true}));
    308 
    309        answerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}?transport=tcp`], username, credential}]});
    310        const candidates = await gatherWithTimeout(answerer, 32000, `a turn (tcp) server`);
    311        ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get any srflx candidates");
    312        ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
    313      } finally {
    314        offerer.close();
    315        answerer.close();
    316      }
    317    },
    318 
    319    async function relayPolicyPreventsSrflx() {
    320      const pc = new RTCPeerConnection();
    321      try {
    322        pc.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}], iceTransportPolicy: "relay"});
    323        const candidates = await gatherWithTimeout(pc, 32000, `a turn (udp) server`);
    324        ok(!candidates.some(c => c.candidate.includes("srflx")), "Should not get a srflx candidate");
    325        ok(candidates.some(c => c.candidate.includes("relay")), "Should get at least one relay candidate");
    326      } finally {
    327        pc.close();
    328      }
    329    },
    330 
    331    async function addOffererStunServerAllowsIceToConnect() {
    332      const offerer = new RTCPeerConnection();
    333      const answerer = new RTCPeerConnection();
    334 
    335      try {
    336        try {
    337          // Both ends are behind a simulated endpoint-independent NAT, which
    338          // requires at least one side to have a srflx candidate to work.
    339          await connect(offerer, answerer, 2000, `no ICE servers`);
    340          ok(false, "ICE should either have failed, or timed out!");
    341        } catch (e) {
    342          if (!(e instanceof Error)) throw e;
    343          ok(true, "ICE should either have failed, or timed out!");
    344        }
    345 
    346        offerer.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    347        await connect(offerer, answerer, 32000, `just a STUN server`);
    348      } finally {
    349        offerer.close();
    350        answerer.close();
    351      }
    352    },
    353 
    354    async function addAnswererStunServerDoesNotAllowIceToConnect() {
    355      const offerer = new RTCPeerConnection();
    356      const answerer = new RTCPeerConnection();
    357 
    358      try {
    359        try {
    360          // Both ends are behind a simulated endpoint-independent NAT, which
    361          // requires at least one side to have a srflx candidate to work.
    362          await connect(offerer, answerer, 2000, `no ICE servers`);
    363          ok(false, "ICE should either have failed, or timed out!");
    364        } catch (e) {
    365          if (!(e instanceof Error)) throw e;
    366          ok(true, "ICE should either have failed, or timed out!");
    367        }
    368 
    369        // This _won't_ help, because the answerer does not get to decide to
    370        // trigger an ICE restart.
    371        answerer.setConfiguration({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    372        try {
    373          await connectNoTrickleWait(offerer, answerer, 2000, `no ICE servers`);
    374          ok(false, "ICE should either have failed, or timed out!");
    375        } catch (e) {
    376          if (!(e instanceof Error)) throw e;
    377          ok(true, "ICE should either have failed, or timed out!");
    378        }
    379      } finally {
    380        offerer.close();
    381        answerer.close();
    382      }
    383    },
    384 
    385    async function addOffererTurnServerAllowsIceToConnect() {
    386      await pushPrefs(
    387          ['media.peerconnection.nat_simulator.filtering_type', 'PORT_DEPENDENT'],
    388          ['media.peerconnection.nat_simulator.mapping_type', 'PORT_DEPENDENT']);
    389 
    390      const offerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    391      const answerer = new RTCPeerConnection({iceServers: [{urls:[`stun:${turnAddressV4}`]}]});
    392 
    393      try {
    394        try {
    395          // Both ends are behind a simulated port-dependent NAT, which
    396          // requires at least one side to have a relay candidate to work.
    397          await connect(offerer, answerer, 2000, `just a STUN server`);
    398          ok(false, "ICE should either have failed, or timed out!");
    399        } catch (e) {
    400          if (!(e instanceof Error)) throw e;
    401          ok(true, "ICE should either have failed, or timed out!");
    402        }
    403 
    404        offerer.setConfiguration({iceServers: [{urls:[`turn:${turnAddressV4}`], username, credential}]});
    405        await connect(offerer, answerer, 32000, `a TURN (udp) server`);
    406      } finally {
    407        offerer.close();
    408        answerer.close();
    409        await SpecialPowers.popPrefEnv();
    410      }
    411    },
    412 
    413  ];
    414 
    415  runNetworkTest(async () => {
    416    const turnServer = iceServersArray.find(server => "username" in server);
    417    username = turnServer.username;
    418    credential = turnServer.credential;
    419    // Just use the first url. It might make sense to look for TURNS first,
    420    // since that will always use a hostname, but on CI we don't have TURNS
    421    // support anyway (see bug 1323439).
    422    const turnHostname = getTurnHostname(turnServer.urls[0]);
    423    turnAddressV4 = await dnsLookupV4(turnHostname);
    424 
    425    await pushPrefs(
    426        ['media.peerconnection.ice.obfuscate_host_addresses', false],
    427        ['media.peerconnection.nat_simulator.filtering_type', 'ENDPOINT_INDEPENDENT'],
    428        ['media.peerconnection.nat_simulator.mapping_type', 'ENDPOINT_INDEPENDENT'],
    429        ['media.peerconnection.ice.loopback', true],
    430        ['media.getusermedia.insecure.enabled', true]);
    431 
    432    for (const test of tests) {
    433      info(`Running test: ${test.name}`);
    434      try {
    435        await test();
    436      } catch (e) {
    437        ok(false, `Caught ${e.name}: ${e.message} ${e.stack}`);
    438      }
    439      info(`Done running test: ${test.name}`);
    440      // Make sure we don't build up a pile of GC work, and also get PCImpl to
    441      // print their timecards.
    442      await new Promise(r => SpecialPowers.exactGC(r));
    443    }
    444 
    445    await SpecialPowers.popPrefEnv();
    446  }, { useIceServer: true });
    447 </script>
    448 </pre>
    449 </body>
    450 </html>