tor-browser

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

RTCConfiguration-iceServers.html (11471B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <title>RTCConfiguration iceServers</title>
      4 <script src='/resources/testharness.js'></script>
      5 <script src='/resources/testharnessreport.js'></script>
      6 <script src='RTCConfiguration-helper.js'></script>
      7 <script>
      8  'use strict';
      9 
     10  // Test is based on the following editor's draft:
     11  // https://w3c.github.io/webrtc-pc/archives/20170605/webrtc.html
     12 
     13  // The following helper function is called from
     14  // RTCConfiguration-helper.js:
     15  //   config_test
     16 
     17  /*
     18    4.3.2.  Interface Definition
     19      [Constructor(optional RTCConfiguration configuration)]
     20      interface RTCPeerConnection : EventTarget {
     21        ...
     22      };
     23 
     24    4.2.1.  RTCConfiguration Dictionary
     25      dictionary RTCConfiguration {
     26        sequence<RTCIceServer>   iceServers = [];
     27        ...
     28      };
     29 
     30    4.2.4.  RTCIceServer Dictionary
     31      dictionary RTCIceServer {
     32        required (DOMString or sequence<DOMString>) urls;
     33                 DOMString                          username;
     34                 DOMString                          credential;
     35      };
     36   */
     37  // RFC 8489 limits the length of the TURN username to 509 bytes:
     38  // https://datatracker.ietf.org/doc/html/rfc8489#section-14.3
     39  const kUsernameOfMaxPermittedLength = 'a'.repeat(509);
     40 
     41  test(() => {
     42    const pc = new RTCPeerConnection();
     43    assert_array_equals(pc.getConfiguration().iceServers, []);
     44  }, 'new RTCPeerConnection() should have default configuration.iceServers of []');
     45 
     46  config_test(makePc => {
     47    makePc({});
     48  }, '{} should succeed');
     49 
     50  config_test(makePc => {
     51    assert_throws_js(TypeError, () =>
     52      makePc({ iceServers: null }));
     53  }, '{ iceServers: null } should throw TypeError');
     54 
     55  config_test(makePc => {
     56    const pc = makePc({ iceServers: undefined });
     57    assert_array_equals(pc.getConfiguration().iceServers, []);
     58  }, '{ iceServers: undefined } should succeed');
     59 
     60  config_test(makePc => {
     61    const pc = makePc({ iceServers: [] });
     62    assert_array_equals(pc.getConfiguration().iceServers, []);
     63  }, '{ iceServers: [] } should succeed');
     64 
     65  config_test(makePc => {
     66    assert_throws_js(TypeError, () =>
     67      makePc({ iceServers: [null] }));
     68  }, '{ iceServers: [null] } should throw TypeError');
     69 
     70  config_test(makePc => {
     71    assert_throws_js(TypeError, () =>
     72      makePc({ iceServers: [undefined] }));
     73  }, '{ iceServers: [undefined] } should throw TypeError');
     74 
     75  config_test(makePc => {
     76    assert_throws_js(TypeError, () =>
     77      makePc({ iceServers: [{}] }));
     78  }, '{ iceServers: [{}] } should throw TypeError');
     79 
     80  config_test(makePc => {
     81    const pc = makePc({ iceServers: [{
     82      urls: 'stun:stun1.example.net'
     83    }] });
     84 
     85    const { iceServers } = pc.getConfiguration();
     86    assert_equals(iceServers.length, 1);
     87 
     88    const server = iceServers[0];
     89    assert_array_equals(server.urls, ['stun:stun1.example.net']);
     90 
     91  }, `with stun server should succeed`);
     92 
     93  config_test(makePc => {
     94    const pc = makePc({ iceServers: [{
     95      urls: ['stun:stun1.example.net']
     96    }] });
     97 
     98    const { iceServers } = pc.getConfiguration();
     99    assert_equals(iceServers.length, 1);
    100 
    101    const server = iceServers[0];
    102    assert_array_equals(server.urls, ['stun:stun1.example.net']);
    103 
    104  }, `with stun server array should succeed`);
    105 
    106  config_test(makePc => {
    107    const pc = makePc({ iceServers: [{
    108      urls: ['stun:stun1.example.net', 'stun:stun2.example.net']
    109    }] });
    110 
    111    const { iceServers } = pc.getConfiguration();
    112    assert_equals(iceServers.length, 1);
    113 
    114    const server = iceServers[0];
    115    assert_array_equals(server.urls, ['stun:stun1.example.net', 'stun:stun2.example.net']);
    116 
    117  }, `with 2 stun servers should succeed`);
    118 
    119  config_test(makePc => {
    120    const pc = makePc({ iceServers: [{
    121      urls: 'turn:turn.example.org',
    122      username: 'user',
    123      credential: 'cred'
    124    }] });
    125 
    126    const { iceServers } = pc.getConfiguration();
    127    assert_equals(iceServers.length, 1);
    128 
    129    const server = iceServers[0];
    130    assert_array_equals(server.urls, ['turn:turn.example.org']);
    131    assert_equals(server.username, 'user');
    132    assert_equals(server.credential, 'cred');
    133 
    134  }, `with turn server, username, credential should succeed`);
    135 
    136  config_test(makePc => {
    137    const pc = makePc({ iceServers: [{
    138      urls: 'turns:turn.example.org',
    139      username: '',
    140      credential: ''
    141    }] });
    142 
    143    const { iceServers } = pc.getConfiguration();
    144    assert_equals(iceServers.length, 1);
    145 
    146    const server = iceServers[0];
    147    assert_array_equals(server.urls, ['turns:turn.example.org']);
    148    assert_equals(server.username, '');
    149    assert_equals(server.credential, '');
    150 
    151  }, `with turns server and empty string username, credential should succeed`);
    152 
    153  config_test(makePc => {
    154    const pc = makePc({ iceServers: [{
    155      urls: 'turn:turn.example.org',
    156      username: '',
    157      credential: ''
    158    }] });
    159 
    160    const { iceServers } = pc.getConfiguration();
    161    assert_equals(iceServers.length, 1);
    162 
    163    const server = iceServers[0];
    164    assert_array_equals(server.urls, ['turn:turn.example.org']);
    165    assert_equals(server.username, '');
    166    assert_equals(server.credential, '');
    167 
    168  }, `with turn server and empty string username, credential should succeed`);
    169 
    170  config_test(makePc => {
    171    const pc = makePc({ iceServers: [{
    172      urls: ['turns:turn.example.org', 'turn:turn.example.net'],
    173      username: 'user',
    174      credential: 'cred'
    175    }] });
    176 
    177    const { iceServers } = pc.getConfiguration();
    178    assert_equals(iceServers.length, 1);
    179 
    180    const server = iceServers[0];
    181    assert_array_equals(server.urls, ['turns:turn.example.org', 'turn:turn.example.net']);
    182    assert_equals(server.username, 'user');
    183    assert_equals(server.credential, 'cred');
    184 
    185  }, `with one turns server, one turn server, username, credential should succeed`);
    186 
    187  config_test(makePc => {
    188    assert_equals(kUsernameOfMaxPermittedLength.length, 509);
    189    const pc = makePc({ iceServers: [{
    190      urls: 'turn:turn.example.net',
    191      username: kUsernameOfMaxPermittedLength,
    192      credential: 'cred'
    193    }] });
    194  }, `with a turn server and a username of 509 characters should succeed`);
    195 
    196  /*
    197    4.3.2.  To set a configuration
    198      11.4. If scheme name is turn or turns, and either of server.username or
    199            server.credential are omitted, then throw an InvalidAccessError.
    200   */
    201  config_test(makePc => {
    202    assert_throws_dom('InvalidAccessError', () =>
    203      makePc({ iceServers: [{
    204        urls: 'turn:turn.example.net'
    205      }] }));
    206  }, 'with turn server and no credentials should throw InvalidAccessError');
    207 
    208  config_test(makePc => {
    209    assert_throws_dom('InvalidAccessError', () =>
    210      makePc({ iceServers: [{
    211        urls: 'turn:turn.example.net',
    212        username: 'user'
    213      }] }));
    214  }, 'with turn server and only username should throw InvalidAccessError');
    215 
    216  config_test(makePc => {
    217    assert_throws_dom('InvalidAccessError', () =>
    218      makePc({ iceServers: [{
    219        urls: 'turn:turn.example.net',
    220        credential: 'cred'
    221      }] }));
    222  }, 'with turn server and only credential should throw InvalidAccessError');
    223 
    224  config_test(makePc => {
    225    assert_throws_dom('InvalidAccessError', () =>
    226      makePc({ iceServers: [{
    227        urls: 'turns:turn.example.net'
    228      }] }));
    229  }, 'with turns server and no credentials should throw InvalidAccessError');
    230 
    231  config_test(makePc => {
    232    assert_throws_dom('InvalidAccessError', () =>
    233      makePc({ iceServers: [{
    234        urls: 'turns:turn.example.net',
    235        username: 'user'
    236      }] }));
    237  }, 'with turns server and only username should throw InvalidAccessError');
    238 
    239  config_test(makePc => {
    240    assert_throws_dom('InvalidAccessError', () =>
    241      makePc({ iceServers: [{
    242        urls: 'turns:turn.example.net',
    243        credential: 'cred'
    244      }] }));
    245  }, 'with turns server and only credential should throw InvalidAccessError');
    246 
    247  config_test(makePc => {
    248    assert_equals(kUsernameOfMaxPermittedLength.length, 509);
    249    assert_throws_dom('InvalidAccessError', () =>
    250      makePc({ iceServers: [{
    251        urls: 'turns:turn.example.net',
    252        username: kUsernameOfMaxPermittedLength + 'a',
    253        credential: 'cred'
    254      }] }));
    255  }, `with a turn server and a username of 510 characters throw InvalidAccessError`);
    256 
    257  /*
    258    4.3.2.  To set a configuration
    259      11.3. For each url in server.urls parse url and obtain scheme name.
    260        - If the scheme name is not implemented by the browser, throw a SyntaxError.
    261        - or if parsing based on the syntax defined in [ RFC7064] and [RFC7065] fails,
    262          throw a SyntaxError.
    263 
    264    [RFC7064] URI Scheme for the Session Traversal Utilities for NAT (STUN) Protocol
    265    3.1.  URI Scheme Syntax
    266      stunURI       = scheme ":" host [ ":" port ]
    267      scheme        = "stun" / "stuns"
    268 
    269    [RFC7065] Traversal Using Relays around NAT (TURN) Uniform Resource Identifiers
    270    3.1.  URI Scheme Syntax
    271      turnURI       = scheme ":" host [ ":" port ]
    272                      [ "?transport=" transport ]
    273      scheme        = "turn" / "turns"
    274      transport     = "udp" / "tcp" / transport-ext
    275      transport-ext = 1*unreserved
    276   */
    277  config_test(makePc => {
    278    assert_throws_dom("SyntaxError", () =>
    279      makePc({ iceServers: [{
    280        urls: ''
    281      }] }));
    282  }, 'with "" url should throw SyntaxError');
    283 
    284  config_test(makePc => {
    285    assert_throws_dom("SyntaxError", () =>
    286      makePc({ iceServers: [{
    287        urls: ['stun:stun1.example.net', '']
    288      }] }));
    289  }, 'with ["stun:stun1.example.net", ""] url should throw SyntaxError');
    290 
    291  config_test(makePc => {
    292    assert_throws_dom("SyntaxError", () =>
    293      makePc({ iceServers: [{
    294        urls: 'relative-url'
    295      }] }));
    296  }, 'with relative url should throw SyntaxError');
    297 
    298  config_test(makePc => {
    299    assert_throws_dom("SyntaxError", () =>
    300      makePc({ iceServers: [{
    301        urls: 'http://example.com'
    302      }] }));
    303  }, 'with http url should throw SyntaxError');
    304 
    305  config_test(makePc => {
    306    assert_throws_dom("SyntaxError", () =>
    307      makePc({ iceServers: [{
    308        urls: 'turn://example.org/foo?x=y'
    309        // `username` and `credential` are not passed because the invalid url
    310        // should be rejected before the check for those arguments.
    311      }] }));
    312  }, 'with invalid turn url should throw SyntaxError');
    313 
    314  config_test(makePc => {
    315    assert_throws_dom("SyntaxError", () =>
    316      makePc({ iceServers: [{
    317        urls: 'stun://example.org/foo?x=y'
    318      }] }));
    319  }, 'with invalid stun url should throw SyntaxError');
    320 
    321  config_test(makePc => {
    322    assert_throws_dom("SyntaxError", () =>
    323      makePc({ iceServers: [{
    324        urls: []
    325      }] }));
    326  }, `with empty urls should throw SyntaxError`);
    327 
    328  test(() => {
    329    const pc = new RTCPeerConnection({ iceServers: [{
    330      urls: 'stun:stun1.example.net'
    331    }] });
    332    let config = pc.getConfiguration();
    333    assert_equals(config.iceServers.length, 1);
    334    pc.setConfiguration({});
    335    config = pc.getConfiguration();
    336    assert_equals(config.iceServers.length, 0);
    337  }, `setConfiguration(config) - without iceServers removes ice servers`);
    338 
    339  config_test(makePc => {
    340    const pc = makePc({ iceServers: [...Array(32)].map((_, i) => ({
    341      urls: `stun:stun${i+1}.example.net`
    342    })) });
    343 
    344    const { iceServers } = pc.getConfiguration();
    345    assert_equals(iceServers.length, 32);
    346 
    347    for (let i = 0; i < 32; i++) {
    348      const server = iceServers[i];
    349      assert_array_equals(server.urls, [`stun:stun${i+1}.example.net`]);
    350    }
    351  }, `with 32 ice servers must succeed`);
    352 </script>