Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/netwerk/test/unit/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 11 kB image not shown  

Quelle  test_socks.js   Sprache: JAVA

 
"use strict";

var CC = Components.Constructor;

const ServerSocket = CC(
  "@mozilla.org/network/server-socket;1",
  "nsIServerSocket",
  "init"
);
const BinaryInputStream = CC(
  "@mozilla.org/binaryinputstream;1",
  "nsIBinaryInputStream",
  "setInputStream"
);
const DirectoryService = CC(
  "@mozilla.org/file/directory_service;1",
  "nsIProperties"
);
const Process = CC("@mozilla.org/process/util;1""nsIProcess""init");

const currentThread =
  Cc["@mozilla.org/thread-manager;1"].getService().currentThread;

var socks_test_server = null;
var socks_listen_port = -1;

function getAvailableBytes(input) {
  var len = 0;

  try {
    len = input.available();
  } catch (e) {}

  return len;
}

function runScriptSubprocess(script, args) {
  var ds = new DirectoryService();
  var bin = ds.get("XREExeF", Ci.nsIFile);
  if (!bin.exists()) {
    do_throw("Can't find xpcshell binary");
  }

  var file = do_get_file(script);
  var proc = new Process(bin);
  var procArgs = [file.path].concat(args);

  proc.run(false, procArgs, procArgs.length);

  return proc;
}

function buf2ip(buf) {
  if (buf.length == 16) {
    var ip =
      ((buf[0] << 4) | buf[1]).toString(16) +
      ":" +
      ((buf[2] << 4) | buf[3]).toString(16) +
      ":" +
      ((buf[4] << 4) | buf[5]).toString(16) +
      ":" +
      ((buf[6] << 4) | buf[7]).toString(16) +
      ":" +
      ((buf[8] << 4) | buf[9]).toString(16) +
      ":" +
      ((buf[10] << 4) | buf[11]).toString(16) +
      ":" +
      ((buf[12] << 4) | buf[13]).toString(16) +
      ":" +
      ((buf[14] << 4) | buf[15]).toString(16);
    for (var i = 8; i >= 2; i--) {
      var re = new RegExp("(^|:)(0(:|$)){" + i + "}");
      var shortip = ip.replace(re, "::");
      if (shortip != ip) {
        return shortip;
      }
    }
    return ip;
  }
  return buf.join(".");
}

function buf2int(buf) {
  var n = 0;

  for (var i in buf) {
    n |= buf[i] << ((buf.length - i - 1) * 8);
  }

  return n;
}

function buf2str(buf) {
  return String.fromCharCode.apply(null, buf);
}

const STATE_WAIT_GREETING = 1;
const STATE_WAIT_SOCKS4_REQUEST = 2;
const STATE_WAIT_SOCKS4_USERNAME = 3;
const STATE_WAIT_SOCKS4_HOSTNAME = 4;
const STATE_WAIT_SOCKS5_GREETING = 5;
const STATE_WAIT_SOCKS5_REQUEST = 6;
const STATE_WAIT_PONG = 7;
const STATE_GOT_PONG = 8;

function SocksClient(server, client_in, client_out) {
  this.server = server;
  this.type = "";
  this.username = "";
  this.dest_name = "";
  this.dest_addr = [];
  this.dest_port = [];

  this.client_in = client_in;
  this.client_out = client_out;
  this.inbuf = [];
  this.outbuf = String();
  this.state = STATE_WAIT_GREETING;
  this.waitRead(this.client_in);
}
SocksClient.prototype = {
  onInputStreamReady(input) {
    var len = getAvailableBytes(input);

    if (len == 0) {
      print("server: client closed!");
      Assert.equal(this.state, STATE_GOT_PONG);
      this.close();
      this.server.testCompleted(this);
      return;
    }

    var bin = new BinaryInputStream(input);
    var data = bin.readByteArray(len);
    this.inbuf = this.inbuf.concat(data);

    switch (this.state) {
      case STATE_WAIT_GREETING:
        this.checkSocksGreeting();
        break;
      case STATE_WAIT_SOCKS4_REQUEST:
        this.checkSocks4Request();
        break;
      case STATE_WAIT_SOCKS4_USERNAME:
        this.checkSocks4Username();
        break;
      case STATE_WAIT_SOCKS4_HOSTNAME:
        this.checkSocks4Hostname();
        break;
      case STATE_WAIT_SOCKS5_GREETING:
        this.checkSocks5Greeting();
        break;
      case STATE_WAIT_SOCKS5_REQUEST:
        this.checkSocks5Request();
        break;
      case STATE_WAIT_PONG:
        this.checkPong();
        break;
      default:
        do_throw("server: read in invalid state!");
    }

    this.waitRead(input);
  },

  onOutputStreamReady(output) {
    var len = output.write(this.outbuf, this.outbuf.length);
    if (len != this.outbuf.length) {
      this.outbuf = this.outbuf.substring(len);
      this.waitWrite(output);
    } else {
      this.outbuf = String();
    }
  },

  waitRead(input) {
    input.asyncWait(this, 0, 0, currentThread);
  },

  waitWrite(output) {
    output.asyncWait(this, 0, 0, currentThread);
  },

  write(buf) {
    this.outbuf += buf;
    this.waitWrite(this.client_out);
  },

  checkSocksGreeting() {
    if (!this.inbuf.length) {
      return;
    }

    if (this.inbuf[0] == 4) {
      print("server: got socks 4");
      this.type = "socks4";
      this.state = STATE_WAIT_SOCKS4_REQUEST;
      this.checkSocks4Request();
    } else if (this.inbuf[0] == 5) {
      print("server: got socks 5");
      this.type = "socks";
      this.state = STATE_WAIT_SOCKS5_GREETING;
      this.checkSocks5Greeting();
    } else {
      do_throw("Unknown socks protocol!");
    }
  },

  checkSocks4Request() {
    if (this.inbuf.length < 8) {
      return;
    }

    Assert.equal(this.inbuf[1], 0x01);

    this.dest_port = this.inbuf.slice(2, 4);
    this.dest_addr = this.inbuf.slice(4, 8);

    this.inbuf = this.inbuf.slice(8);
    this.state = STATE_WAIT_SOCKS4_USERNAME;
    this.checkSocks4Username();
  },

  readString() {
    var i = this.inbuf.indexOf(0);
    var str = null;

    if (i >= 0) {
      var buf = this.inbuf.slice(0, i);
      str = buf2str(buf);
      this.inbuf = this.inbuf.slice(i + 1);
    }

    return str;
  },

  checkSocks4Username() {
    var str = this.readString();

    if (str == null) {
      return;
    }

    this.username = str;
    if (
      this.dest_addr[0] == 0 &&
      this.dest_addr[1] == 0 &&
      this.dest_addr[2] == 0 &&
      this.dest_addr[3] != 0
    ) {
      this.state = STATE_WAIT_SOCKS4_HOSTNAME;
      this.checkSocks4Hostname();
    } else {
      this.sendSocks4Response();
    }
  },

  checkSocks4Hostname() {
    var str = this.readString();

    if (str == null) {
      return;
    }

    this.dest_name = str;
    this.sendSocks4Response();
  },

  sendSocks4Response() {
    this.outbuf = "\x00\x5a\x00\x00\x00\x00\x00\x00";
    this.sendPing();
  },

  checkSocks5Greeting() {
    if (this.inbuf.length < 2) {
      return;
    }
    var nmethods = this.inbuf[1];
    if (this.inbuf.length < 2 + nmethods) {
      return;
    }

    Assert.ok(nmethods >= 1);
    var methods = this.inbuf.slice(2, 2 + nmethods);
    Assert.ok(0 in methods);

    this.inbuf = [];
    this.state = STATE_WAIT_SOCKS5_REQUEST;
    this.write("\x05\x00");
  },

  checkSocks5Request() {
    if (this.inbuf.length < 4) {
      return;
    }

    Assert.equal(this.inbuf[0], 0x05);
    Assert.equal(this.inbuf[1], 0x01);
    Assert.equal(this.inbuf[2], 0x00);

    var atype = this.inbuf[3];
    var len;
    var name = false;

    switch (atype) {
      case 0x01:
        len = 4;
        break;
      case 0x03:
        len = this.inbuf[4];
        name = true;
        break;
      case 0x04:
        len = 16;
        break;
      default:
        do_throw("Unknown address type " + atype);
    }

    if (name) {
      if (this.inbuf.length < 4 + len + 1 + 2) {
        return;
      }

      let buf = this.inbuf.slice(5, 5 + len);
      this.dest_name = buf2str(buf);
      len += 1;
    } else {
      if (this.inbuf.length < 4 + len + 2) {
        return;
      }

      this.dest_addr = this.inbuf.slice(4, 4 + len);
    }

    len += 4;
    this.dest_port = this.inbuf.slice(len, len + 2);
    this.inbuf = this.inbuf.slice(len + 2);
    this.sendSocks5Response();
  },

  sendSocks5Response() {
    if (this.dest_addr.length == 16) {
      // send a successful response with the address, [::1]:80
      this.outbuf +=
        "\x05\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x80";
    } else {
      // send a successful response with the address, 127.0.0.1:80
      this.outbuf += "\x05\x00\x00\x01\x7f\x00\x00\x01\x00\x80";
    }
    this.sendPing();
  },

  sendPing() {
    print("server: sending ping");
    this.state = STATE_WAIT_PONG;
    this.outbuf += "PING!";
    this.inbuf = [];
    this.waitWrite(this.client_out);
  },

  checkPong() {
    var pong = buf2str(this.inbuf);
    Assert.equal(pong, "PONG!");
    this.state = STATE_GOT_PONG;
  },

  close() {
    this.client_in.close();
    this.client_out.close();
  },
};

function SocksTestServer() {
  this.listener = ServerSocket(-1, true, -1);
  socks_listen_port = this.listener.port;
  print("server: listening on", socks_listen_port);
  this.listener.asyncListen(this);
  this.test_cases = [];
  this.client_connections = [];
  this.client_subprocess = null;
  // port is used as the ID for test cases
  this.test_port_id = 8000;
  this.tests_completed = 0;
}
SocksTestServer.prototype = {
  addTestCase(test) {
    test.finished = false;
    test.port = this.test_port_id++;
    this.test_cases.push(test);
  },

  pickTest(id) {
    for (var i in this.test_cases) {
      var test = this.test_cases[i];
      if (test.port == id) {
        this.tests_completed++;
        return test;
      }
    }
    do_throw("No test case with id " + id);
    return null;
  },

  testCompleted(client) {
    var port_id = buf2int(client.dest_port);
    var test = this.pickTest(port_id);

    print("server: test finished", test.port);
    Assert.ok(test != null);
    Assert.equal(test.expectedType || test.type, client.type);
    Assert.equal(test.port, port_id);

    if (test.remote_dns) {
      Assert.equal(test.host, client.dest_name);
    } else {
      Assert.equal(test.host, buf2ip(client.dest_addr));
    }

    if (this.test_cases.length == this.tests_completed) {
      print("server: all tests completed");
      this.close();
      do_test_finished();
    }
  },

  runClientSubprocess() {
    var argv = [];

    // marshaled: socks_ver|server_port|dest_host|dest_port|<remote|local>
    for (var test of this.test_cases) {
      var arg =
        test.type +
        "|" +
        String(socks_listen_port) +
        "|" +
        test.host +
        "|" +
        test.port +
        "|";
      if (test.remote_dns) {
        arg += "remote";
      } else {
        arg += "local";
      }
      print("server: using test case", arg);
      argv.push(arg);
    }

    this.client_subprocess = runScriptSubprocess(
      "socks_client_subprocess.js",
      argv
    );
  },

  onSocketAccepted(socket, trans) {
    print("server: got client connection");
    var input = trans.openInputStream(0, 0, 0);
    var output = trans.openOutputStream(0, 0, 0);
    var client = new SocksClient(this, input, output);
    this.client_connections.push(client);
  },

  onStopListening() {},

  close() {
    if (this.client_subprocess) {
      try {
        this.client_subprocess.kill();
      } catch (x) {
        do_note_exception(x, "Killing subprocess failed");
      }
      this.client_subprocess = null;
    }
    this.client_connections = [];
    if (this.listener) {
      this.listener.close();
      this.listener = null;
    }
  },
};

function run_test() {
  socks_test_server = new SocksTestServer();

  socks_test_server.addTestCase({
    type: "socks4",
    host: "127.0.0.1",
    remote_dns: false,
  });
  socks_test_server.addTestCase({
    type: "socks4",
    host: "12345.xxx",
    remote_dns: true,
  });
  socks_test_server.addTestCase({
    type: "socks4",
    expectedType: "socks",
    host: "::1",
    remote_dns: false,
  });
  socks_test_server.addTestCase({
    type: "socks",
    host: "127.0.0.1",
    remote_dns: false,
  });
  socks_test_server.addTestCase({
    type: "socks",
    host: "abcdefg.xxx",
    remote_dns: true,
  });
  socks_test_server.addTestCase({
    type: "socks",
    host: "::1",
    remote_dns: false,
  });
  socks_test_server.runClientSubprocess();

  do_test_pending();
}

Messung V0.5
C=92 H=92 G=91

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.