tor-browser

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

test_anonymous-coalescing.js (4741B)


      1 /*
      2 - test to check we use only a single connection for both onymous and anonymous requests over an existing h2 session
      3 - request from a domain w/o LOAD_ANONYMOUS flag
      4 - request again from the same domain, but different URI, with LOAD_ANONYMOUS flag, check the client is using the same conn
      5 - close all and do it in the opposite way (do an anonymous req first)
      6 */
      7 
      8 "use strict";
      9 
     10 const { NodeHTTP2Server } = ChromeUtils.importESModule(
     11  "resource://testing-common/NodeServer.sys.mjs"
     12 );
     13 
     14 let server;
     15 
     16 add_setup(async function test_setup() {
     17  do_get_profile();
     18  Services.prefs.setBoolPref("network.http.http2.enabled", true);
     19  Services.prefs.setCharPref("network.dns.localDomains", "foo.example.com");
     20 
     21  server = new NodeHTTP2Server();
     22  await server.start();
     23  registerCleanupFunction(async () => {
     24    await server.stop();
     25  });
     26 
     27  // Register path handlers for all test endpoints - copy from moz-http2.js
     28  await server.registerPathHandler("/origin-1", (req, resp) => {
     29    resp.setHeader("x-client-port", req.socket.remotePort);
     30    resp.writeHead(200, { "Content-Type": "text/plain" });
     31    resp.end("origin-1");
     32  });
     33  await server.registerPathHandler("/origin-2", (req, resp) => {
     34    resp.setHeader("x-client-port", req.socket.remotePort);
     35    resp.writeHead(200, { "Content-Type": "text/plain" });
     36    resp.end("origin-2");
     37  });
     38  await server.registerPathHandler("/origin-3", (req, resp) => {
     39    resp.setHeader("x-client-port", req.socket.remotePort);
     40    resp.writeHead(200, { "Content-Type": "text/plain" });
     41    resp.end("origin-3");
     42  });
     43  await server.registerPathHandler("/origin-4", (req, resp) => {
     44    resp.setHeader("x-client-port", req.socket.remotePort);
     45    resp.writeHead(200, { "Content-Type": "text/plain" });
     46    resp.end("origin-4");
     47  });
     48 });
     49 
     50 registerCleanupFunction(() => {
     51  Services.prefs.clearUserPref("network.http.http2.enabled");
     52  Services.prefs.clearUserPref("network.dns.localDomains");
     53 });
     54 
     55 function makeChan(origin) {
     56  return NetUtil.newChannel({
     57    uri: origin,
     58    loadUsingSystemPrincipal: true,
     59  }).QueryInterface(Ci.nsIHttpChannel);
     60 }
     61 
     62 function channelOpenPromise(chan, loadFlags = 0) {
     63  return new Promise((resolve, reject) => {
     64    chan.loadFlags = Ci.nsIChannel.LOAD_INITIAL_DOCUMENT_URI | loadFlags;
     65 
     66    function finish(req, buffer) {
     67      try {
     68        Assert.ok(req instanceof Ci.nsIHttpChannel);
     69        Assert.ok(Components.isSuccessCode(req.status));
     70        Assert.equal(req.responseStatus, 200);
     71        const clientPort = parseInt(req.getResponseHeader("x-client-port"));
     72        resolve({ req, buffer, clientPort });
     73      } catch (e) {
     74        reject(e);
     75      }
     76    }
     77 
     78    chan.asyncOpen(new ChannelListener(finish, null, CL_ALLOW_UNKNOWN_CL));
     79  });
     80 }
     81 
     82 add_task(async function test_anonymous_coalescing_sequence() {
     83  let currentPort = 0;
     84 
     85  // Test 1: First non-anonymous request
     86  info("Test 1: First non-anonymous request");
     87  let chan = makeChan(`https://foo.example.com:${server.port()}/origin-1`);
     88  let result = await channelOpenPromise(chan);
     89  Assert.notEqual(currentPort, result.clientPort);
     90  currentPort = result.clientPort;
     91 
     92  // Test 2: Same request to mark connection as experienced
     93  info("Test 2: Second non-anonymous request (same endpoint)");
     94  chan = makeChan(`https://foo.example.com:${server.port()}/origin-1`);
     95  result = await channelOpenPromise(chan);
     96  Assert.equal(currentPort, result.clientPort);
     97 
     98  // Test 3: Anonymous request should reuse connection
     99  info("Test 3: Anonymous request should reuse connection");
    100  chan = makeChan(`https://foo.example.com:${server.port()}/origin-2`);
    101  result = await channelOpenPromise(chan, Ci.nsIRequest.LOAD_ANONYMOUS);
    102  Assert.equal(currentPort, result.clientPort);
    103 
    104  // Test 4: Force new connection with anonymous request
    105  info("Test 4: Force new connection with anonymous request");
    106  chan = makeChan(`https://foo.example.com:${server.port()}/origin-3`);
    107  result = await channelOpenPromise(
    108    chan,
    109    Ci.nsIRequest.LOAD_ANONYMOUS | Ci.nsIRequest.LOAD_FRESH_CONNECTION
    110  );
    111  Assert.notEqual(currentPort, result.clientPort);
    112  currentPort = result.clientPort;
    113 
    114  // Test 5: Same anonymous request to mark connection as experienced
    115  info("Test 5: Same anonymous request (mark connection experienced)");
    116  chan = makeChan(`https://foo.example.com:${server.port()}/origin-3`);
    117  result = await channelOpenPromise(chan, Ci.nsIRequest.LOAD_ANONYMOUS);
    118  Assert.equal(currentPort, result.clientPort);
    119 
    120  // Test 6: Non-anonymous request should reuse connection
    121  info("Test 6: Non-anonymous request should reuse connection");
    122  chan = makeChan(`https://foo.example.com:${server.port()}/origin-4`);
    123  result = await channelOpenPromise(chan);
    124  Assert.equal(currentPort, result.clientPort);
    125 });