tor-browser

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

test_webtransport_simple.js (12130B)


      1 //
      2 //  Simple WebTransport test
      3 //
      4 
      5 /* import-globals-from head_webtransport.js */
      6 
      7 "use strict";
      8 
      9 var h3Port;
     10 var host;
     11 
     12 var { setTimeout } = ChromeUtils.importESModule(
     13  "resource://gre/modules/Timer.sys.mjs"
     14 );
     15 
     16 registerCleanupFunction(async () => {
     17  Services.prefs.clearUserPref("network.dns.localDomains");
     18  Services.prefs.clearUserPref(
     19    "network.http.http3.alt-svc-mapping-for-testing"
     20  );
     21 });
     22 
     23 add_task(async function setup() {
     24  await http3_setup_tests("h3");
     25 
     26  h3Port = Services.env.get("MOZHTTP3_PORT");
     27  Assert.notEqual(h3Port, null);
     28  Assert.notEqual(h3Port, "");
     29  host = "foo.example.com:" + h3Port;
     30 });
     31 
     32 function makeChan(url) {
     33  let chan = NetUtil.newChannel({
     34    uri: url,
     35    loadUsingSystemPrincipal: true,
     36    contentPolicyType: Ci.nsIContentPolicy.TYPE_DOCUMENT,
     37  }).QueryInterface(Ci.nsIHttpChannel);
     38  chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
     39  return chan;
     40 }
     41 
     42 function channelOpenPromise(chan, flags) {
     43  // eslint-disable-next-line no-async-promise-executor
     44  return new Promise(async resolve => {
     45    function finish(req, buffer) {
     46      resolve([req, buffer]);
     47    }
     48    chan.asyncOpen(new ChannelListener(finish, null, flags));
     49  });
     50 }
     51 
     52 function bytesFromString(str) {
     53  return new TextEncoder().encode(str);
     54 }
     55 
     56 add_task(async function test_wt_datagram() {
     57  let webTransport = NetUtil.newWebTransport();
     58  let listener = new WebTransportListener().QueryInterface(
     59    Ci.WebTransportSessionEventListener
     60  );
     61 
     62  let pReady = new Promise(resolve => {
     63    listener.ready = resolve;
     64  });
     65  let pSize = new Promise(resolve => {
     66    listener.onMaxDatagramSize = resolve;
     67  });
     68  let pOutcome = new Promise(resolve => {
     69    listener.onDatagramOutcome = resolve;
     70  });
     71 
     72  webTransport.asyncConnect(
     73    NetUtil.newURI(`https://${host}/success`),
     74    true,
     75    [],
     76    Services.scriptSecurityManager.getSystemPrincipal(),
     77    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
     78    listener
     79  );
     80 
     81  await pReady;
     82 
     83  webTransport.getMaxDatagramSize();
     84  let size = await pSize;
     85  info("max size:" + size);
     86 
     87  let rawData = new Uint8Array(size);
     88  rawData.fill(42);
     89 
     90  webTransport.sendDatagram(rawData, 1);
     91  let { id, outcome } = await pOutcome;
     92  Assert.equal(id, 1);
     93  Assert.equal(outcome, Ci.WebTransportSessionEventListener.SENT);
     94 
     95  let chan = makeChan(`https://${host}/get_webtransport_datagram`);
     96  let [req, buffer] = await channelOpenPromise(chan);
     97  Assert.equal(req.protocolVersion, "h3");
     98 
     99  Assert.deepEqual(bytesFromString(buffer), rawData);
    100 
    101  webTransport.getMaxDatagramSize();
    102  size = await pSize;
    103  info("max size:" + size);
    104 
    105  rawData = new Uint8Array(size + 1);
    106  webTransport.sendDatagram(rawData, 2);
    107 
    108  pOutcome = new Promise(resolve => {
    109    listener.onDatagramOutcome = resolve;
    110  });
    111  ({ id, outcome } = await pOutcome);
    112  Assert.equal(id, 2);
    113  Assert.equal(
    114    outcome,
    115    Ci.WebTransportSessionEventListener.DROPPED_TOO_MUCH_DATA
    116  );
    117 
    118  webTransport.closeSession(0, "");
    119 });
    120 
    121 add_task(async function test_connect_wt() {
    122  let webTransport = NetUtil.newWebTransport();
    123 
    124  await new Promise(resolve => {
    125    let listener = new WebTransportListener().QueryInterface(
    126      Ci.WebTransportSessionEventListener
    127    );
    128    listener.ready = resolve;
    129 
    130    webTransport.asyncConnect(
    131      NetUtil.newURI(`https://${host}/success`),
    132      true,
    133      [],
    134      Services.scriptSecurityManager.getSystemPrincipal(),
    135      Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    136      listener
    137    );
    138  });
    139 
    140  webTransport.closeSession(0, "");
    141 });
    142 
    143 add_task(async function test_redirect_wt() {
    144  let webTransport = NetUtil.newWebTransport();
    145 
    146  await new Promise(resolve => {
    147    let listener = new WebTransportListener().QueryInterface(
    148      Ci.WebTransportSessionEventListener
    149    );
    150 
    151    listener.closed = resolve;
    152 
    153    webTransport.asyncConnect(
    154      NetUtil.newURI(`https://${host}/redirect`),
    155      true,
    156      [],
    157      Services.scriptSecurityManager.getSystemPrincipal(),
    158      Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    159      listener
    160    );
    161  });
    162 });
    163 
    164 add_task(async function test_reject() {
    165  let webTransport = NetUtil.newWebTransport();
    166 
    167  await new Promise(resolve => {
    168    let listener = new WebTransportListener().QueryInterface(
    169      Ci.WebTransportSessionEventListener
    170    );
    171    listener.closed = resolve;
    172 
    173    webTransport.asyncConnect(
    174      NetUtil.newURI(`https://${host}/reject`),
    175      true,
    176      [],
    177      Services.scriptSecurityManager.getSystemPrincipal(),
    178      Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    179      listener
    180    );
    181  });
    182 });
    183 
    184 async function test_closed(path) {
    185  let webTransport = NetUtil.newWebTransport();
    186 
    187  let listener = new WebTransportListener().QueryInterface(
    188    Ci.WebTransportSessionEventListener
    189  );
    190 
    191  let pReady = new Promise(resolve => {
    192    listener.ready = resolve;
    193  });
    194  let pClose = new Promise(resolve => {
    195    listener.closed = resolve;
    196  });
    197  webTransport.asyncConnect(
    198    NetUtil.newURI(`https://${host}${path}`),
    199    true,
    200    [],
    201    Services.scriptSecurityManager.getSystemPrincipal(),
    202    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    203    listener
    204  );
    205 
    206  await pReady;
    207  await pClose;
    208 }
    209 
    210 add_task(async function test_closed_0ms() {
    211  await test_closed("/closeafter0ms");
    212 });
    213 
    214 add_task(async function test_closed_100ms() {
    215  await test_closed("/closeafter100ms");
    216 });
    217 
    218 add_task(async function test_wt_stream_create() {
    219  let webTransport = NetUtil.newWebTransport().QueryInterface(
    220    Ci.nsIWebTransport
    221  );
    222 
    223  await new Promise(resolve => {
    224    let listener = new WebTransportListener().QueryInterface(
    225      Ci.WebTransportSessionEventListener
    226    );
    227    listener.ready = resolve;
    228 
    229    webTransport.asyncConnect(
    230      NetUtil.newURI(`https://${host}/success`),
    231      true,
    232      [],
    233      Services.scriptSecurityManager.getSystemPrincipal(),
    234      Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    235      listener
    236    );
    237  });
    238 
    239  await streamCreatePromise(webTransport, true);
    240  await streamCreatePromise(webTransport, false);
    241 
    242  webTransport.closeSession(0, "");
    243 });
    244 
    245 add_task(async function test_wt_stream_send_and_stats() {
    246  let webTransport = NetUtil.newWebTransport().QueryInterface(
    247    Ci.nsIWebTransport
    248  );
    249 
    250  await new Promise(resolve => {
    251    let listener = new WebTransportListener().QueryInterface(
    252      Ci.WebTransportSessionEventListener
    253    );
    254    listener.ready = resolve;
    255 
    256    webTransport.asyncConnect(
    257      NetUtil.newURI(`https://${host}/success`),
    258      true,
    259      [],
    260      Services.scriptSecurityManager.getSystemPrincipal(),
    261      Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    262      listener
    263    );
    264  });
    265 
    266  let stream = await streamCreatePromise(webTransport, false);
    267  let outputStream = stream.outputStream;
    268 
    269  let data = "1234567890ABC";
    270  outputStream.write(data, data.length);
    271 
    272  // We need some time to send the packet out.
    273  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
    274  await new Promise(resolve => setTimeout(resolve, 2000));
    275 
    276  let stats = await sendStreamStatsPromise(stream);
    277  Assert.equal(stats.bytesSent, data.length);
    278 
    279  webTransport.closeSession(0, "");
    280 });
    281 
    282 add_task(async function test_wt_receive_stream_and_stats() {
    283  let webTransport = NetUtil.newWebTransport().QueryInterface(
    284    Ci.nsIWebTransport
    285  );
    286 
    287  let listener = new WebTransportListener().QueryInterface(
    288    Ci.WebTransportSessionEventListener
    289  );
    290 
    291  let pReady = new Promise(resolve => {
    292    listener.ready = resolve;
    293  });
    294  let pStreamReady = new Promise(resolve => {
    295    listener.streamAvailable = resolve;
    296  });
    297  webTransport.asyncConnect(
    298    NetUtil.newURI(`https://${host}/create_unidi_stream_and_hello`),
    299    true,
    300    [],
    301    Services.scriptSecurityManager.getSystemPrincipal(),
    302    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    303    listener
    304  );
    305 
    306  await pReady;
    307  let stream = await pStreamReady;
    308 
    309  let data = await new Promise(resolve => {
    310    let handler = new inputStreamReader().QueryInterface(
    311      Ci.nsIInputStreamCallback
    312    );
    313    handler.finish = resolve;
    314    let inputStream = stream.inputStream;
    315    inputStream.asyncWait(handler, 0, 0, Services.tm.currentThread);
    316  });
    317 
    318  info("data: " + data);
    319  Assert.equal(data, "qwerty");
    320 
    321  let stats = await receiveStreamStatsPromise(stream);
    322  Assert.equal(stats.bytesReceived, data.length);
    323 
    324  stream.sendStopSending(0);
    325 
    326  webTransport.closeSession(0, "");
    327 });
    328 
    329 add_task(async function test_wt_outgoing_bidi_stream() {
    330  let webTransport = NetUtil.newWebTransport().QueryInterface(
    331    Ci.nsIWebTransport
    332  );
    333 
    334  await new Promise(resolve => {
    335    let listener = new WebTransportListener().QueryInterface(
    336      Ci.WebTransportSessionEventListener
    337    );
    338    listener.ready = resolve;
    339 
    340    webTransport.asyncConnect(
    341      NetUtil.newURI(`https://${host}/success`),
    342      true,
    343      [],
    344      Services.scriptSecurityManager.getSystemPrincipal(),
    345      Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    346      listener
    347    );
    348  });
    349 
    350  let stream = await streamCreatePromise(webTransport, true);
    351  let outputStream = stream.outputStream;
    352 
    353  let data = "1234567";
    354  outputStream.write(data, data.length);
    355 
    356  let received = await new Promise(resolve => {
    357    let handler = new inputStreamReader().QueryInterface(
    358      Ci.nsIInputStreamCallback
    359    );
    360    handler.finish = resolve;
    361    let inputStream = stream.inputStream;
    362    inputStream.asyncWait(handler, 0, 0, Services.tm.currentThread);
    363  });
    364 
    365  info("received: " + received);
    366  Assert.equal(received, data);
    367 
    368  let stats = await sendStreamStatsPromise(stream);
    369  Assert.equal(stats.bytesSent, data.length);
    370 
    371  stats = await receiveStreamStatsPromise(stream);
    372  Assert.equal(stats.bytesReceived, data.length);
    373 
    374  webTransport.closeSession(0, "");
    375 });
    376 
    377 add_task(async function test_wt_incoming_bidi_stream() {
    378  let webTransport = NetUtil.newWebTransport().QueryInterface(
    379    Ci.nsIWebTransport
    380  );
    381 
    382  let listener = new WebTransportListener().QueryInterface(
    383    Ci.WebTransportSessionEventListener
    384  );
    385 
    386  let pReady = new Promise(resolve => {
    387    listener.ready = resolve;
    388  });
    389  let pStreamReady = new Promise(resolve => {
    390    listener.streamAvailable = resolve;
    391  });
    392  webTransport.asyncConnect(
    393    NetUtil.newURI(`https://${host}/create_bidi_stream`),
    394    true,
    395    [],
    396    Services.scriptSecurityManager.getSystemPrincipal(),
    397    Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    398    listener
    399  );
    400 
    401  await pReady;
    402  let stream = await pStreamReady;
    403 
    404  let outputStream = stream.outputStream;
    405 
    406  let data = "12345678";
    407  outputStream.write(data, data.length);
    408 
    409  let received = await new Promise(resolve => {
    410    let handler = new inputStreamReader().QueryInterface(
    411      Ci.nsIInputStreamCallback
    412    );
    413    handler.finish = resolve;
    414    let inputStream = stream.inputStream;
    415    inputStream.asyncWait(handler, 0, 0, Services.tm.currentThread);
    416  });
    417 
    418  info("received: " + received);
    419  Assert.equal(received, data);
    420 
    421  let stats = await sendStreamStatsPromise(stream);
    422  Assert.equal(stats.bytesSent, data.length);
    423 
    424  stats = await receiveStreamStatsPromise(stream);
    425  Assert.equal(stats.bytesReceived, data.length);
    426 
    427  webTransport.closeSession(0, "");
    428 });
    429 
    430 async function createWebTransportAndConnect() {
    431  let webTransport = NetUtil.newWebTransport();
    432 
    433  await new Promise(resolve => {
    434    let listener = new WebTransportListener().QueryInterface(
    435      Ci.WebTransportSessionEventListener
    436    );
    437    listener.ready = resolve;
    438 
    439    webTransport.asyncConnect(
    440      NetUtil.newURI(`https://${host}/success`),
    441      true,
    442      [],
    443      Services.scriptSecurityManager.getSystemPrincipal(),
    444      Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL,
    445      listener
    446    );
    447  });
    448 
    449  return webTransport;
    450 }
    451 
    452 add_task(async function test_multple_webtransport_connnection() {
    453  let webTransports = [];
    454  for (let i = 0; i < 3; i++) {
    455    let transport = await createWebTransportAndConnect();
    456    webTransports.push(transport);
    457  }
    458 
    459  let first = webTransports[0];
    460  await streamCreatePromise(first, true);
    461 
    462  for (let i = 0; i < 3; i++) {
    463    webTransports[i].closeSession(0, "");
    464  }
    465 });