tor-browser

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

test_http2_proxy_concurrent_stream.js (4238B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 "use strict";
      6 
      7 /* import-globals-from head_cache.js */
      8 /* import-globals-from head_cookies.js */
      9 /* import-globals-from head_channels.js */
     10 
     11 const { setTimeout } = ChromeUtils.importESModule(
     12  "resource://gre/modules/Timer.sys.mjs"
     13 );
     14 
     15 const {
     16  NodeHTTPServer,
     17  NodeHTTPSServer,
     18  NodeHTTP2Server,
     19  NodeHTTP2ProxyServer,
     20  with_node_servers,
     21 } = ChromeUtils.importESModule("resource://testing-common/NodeServer.sys.mjs");
     22 
     23 add_setup(async function () {
     24  Services.prefs.setBoolPref("network.proxy.allow_hijacking_localhost", true);
     25  let certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
     26    Ci.nsIX509CertDB
     27  );
     28  addCertFromFile(certdb, "http2-ca.pem", "CTu,u,u");
     29  addCertFromFile(certdb, "proxy-ca.pem", "CTu,u,u");
     30  registerCleanupFunction(() => {
     31    Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
     32    Services.prefs.clearUserPref("network.proxy.allow_hijacking_localhost");
     33  });
     34 });
     35 
     36 function makeChan(uri) {
     37  let chan = NetUtil.newChannel({
     38    uri,
     39    loadUsingSystemPrincipal: true,
     40  }).QueryInterface(Ci.nsIHttpChannel);
     41  chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI;
     42  return chan;
     43 }
     44 
     45 function channelOpenPromise(chan, flags) {
     46  return new Promise(resolve => {
     47    function finish(req, buffer) {
     48      resolve([req, buffer]);
     49    }
     50    chan.asyncOpen(new ChannelListener(finish, null, flags));
     51  });
     52 }
     53 
     54 function registerServerNamePathHandler(server, path) {
     55  return server.registerPathHandler(path, (req, resp) => {
     56    // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
     57    setTimeout(() => {
     58      resp.writeHead(200);
     59      resp.end(global.server_name);
     60    }, 1000);
     61  });
     62 }
     63 
     64 async function run_http2_proxy_test(
     65  maxConcurrentStreams,
     66  maxStreamId,
     67  testId = ""
     68 ) {
     69  Services.obs.notifyObservers(null, "net:prune-all-connections");
     70  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
     71  await new Promise(resolve => setTimeout(resolve, 1000));
     72 
     73  Services.prefs.setIntPref("network.http.http2.max_stream_id", maxStreamId);
     74 
     75  let proxy = new NodeHTTP2ProxyServer();
     76  await proxy.start(0, false, maxConcurrentStreams);
     77  registerCleanupFunction(async () => {
     78    await proxy.stop();
     79  });
     80 
     81  await with_node_servers(
     82    [NodeHTTPServer, NodeHTTPSServer, NodeHTTP2Server],
     83    async server => {
     84      await server.execute(
     85        `global.server_name = "${server.constructor.name}";`
     86      );
     87      await registerServerNamePathHandler(server, "/test");
     88 
     89      await channelOpenPromise(
     90        makeChan(`${server.origin()}/test`),
     91        CL_ALLOW_UNKNOWN_CL
     92      );
     93 
     94      // Wait a bit to ensure the first proxy connection is established.
     95      // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
     96      await new Promise(resolve => setTimeout(resolve, 1000));
     97 
     98      let promises = [];
     99      for (let i = 0; i < 20; i++) {
    100        let promise = channelOpenPromise(
    101          makeChan(`${server.origin()}/test?test=${testId}&id=${i}`),
    102          CL_ALLOW_UNKNOWN_CL
    103        );
    104 
    105        promises.push(promise);
    106      }
    107 
    108      let results = await Promise.all(promises);
    109      for (let [req, buff] of results) {
    110        equal(req.status, Cr.NS_OK);
    111        equal(req.QueryInterface(Ci.nsIHttpChannel).responseStatus, 200);
    112        equal(buff, server.constructor.name);
    113      }
    114      await server.stop();
    115    }
    116  );
    117 
    118  await proxy.stop();
    119 }
    120 
    121 // Test case 1: High concurrency, high stream ID limit
    122 add_task(async function test_high_concurrency_high_stream_id() {
    123  await run_http2_proxy_test(100, 0x7800000, "t1");
    124 });
    125 
    126 // Test case 2: Low concurrency, high stream ID limit
    127 add_task(async function test_low_concurrency_high_stream_id() {
    128  await run_http2_proxy_test(3, 0x7800000, "t2");
    129 });
    130 
    131 // Test case 3: High concurrency, low stream ID limit
    132 add_task(async function test_high_concurrency_low_stream_id() {
    133  await run_http2_proxy_test(100, 10, "t3");
    134 });
    135 
    136 // Test case 4: Low concurrency, low stream ID limit
    137 add_task(async function test_low_concurrency_low_stream_id() {
    138  await run_http2_proxy_test(3, 10, "t4");
    139 });