tor-browser

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

commit c9fb372171f7019d122c2b864903a2aee8546195
parent 8cfad39176be94c2534ada4abc8c693998f48026
Author: Valentin Gosu <valentin.gosu@gmail.com>
Date:   Tue, 25 Nov 2025 14:42:46 +0000

Bug 2001617 - Add plaintext WS server r=necko-reviewers,kershaw

Differential Revision: https://phabricator.services.mozilla.com/D273787

Diffstat:
Mnetwerk/test/httpserver/NodeServer.sys.mjs | 57++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Mnetwerk/test/unit/test_websocket_server.js | 37+++++++++++++++++++++++++++++++++++++
Mtesting/xpcshell/moz-http2/moz-http2.js | 3---
3 files changed, 89 insertions(+), 8 deletions(-)

diff --git a/netwerk/test/httpserver/NodeServer.sys.mjs b/netwerk/test/httpserver/NodeServer.sys.mjs @@ -875,6 +875,52 @@ export class NodeWebSocketServer extends BaseNodeServer { } } +// unencrypted websocket server + +class NodeWebSocketPlainServerCode extends BaseNodeHTTPServerCode { + static async startServer(port) { + const http = require("http"); + global.server = http.createServer(BaseNodeHTTPServerCode.globalHandler); + + let node_ws_root = `${__dirname}/../node-ws`; + const WS = require(`${node_ws_root}/lib/websocket`); + WS.Server = require(`${node_ws_root}/lib/websocket-server`); + global.webSocketServer = new WS.Server({ server: global.server }); + global.webSocketServer.on("connection", function connection(ws) { + ws.on("message", data => + NodeWebSocketServerCode.messageHandler(data, ws) + ); + }); + + let serverPort = await ADB.listenAndForwardPort(global.server, port); + return serverPort; + } +} + +export class NodeWebSocketPlainServer extends BaseNodeServer { + _protocol = "ws"; + /// Starts the server + /// @port - default 0 + /// when provided, will attempt to listen on that port. + async start(port = 0) { + this.processId = await NodeServer.fork(); + + await this.execute(BaseNodeHTTPServerCode); + await this.execute(NodeWebSocketServerCode); + await this.execute(NodeWebSocketPlainServerCode); + await this.execute(ADB); + this._port = await this.execute( + `NodeWebSocketPlainServerCode.startServer(${port})` + ); + await this.execute(`global.path_handlers = {};`); + await this.execute(`global.wsInputHandler = null;`); + } + + async registerMessageHandler(handler) { + return this.execute(`global.wsInputHandler = ${handler.toString()}`); + } +} + // websocket http2 server // This code is inspired by // https://github.com/szmarczak/http2-wrapper/blob/master/examples/ws/server.js @@ -1029,10 +1075,11 @@ export class WebSocketConnection { } } - static makeWebSocketChan() { - let chan = Cc["@mozilla.org/network/protocol;1?name=wss"].createInstance( - Ci.nsIWebSocketChannel - ); + static makeWebSocketChan(url) { + let protocol = url.startsWith("wss:") ? "wss" : "ws"; + let chan = Cc[ + `@mozilla.org/network/protocol;1?name=${protocol}` + ].createInstance(Ci.nsIWebSocketChannel); chan.initLoadInfo( null, // aLoadingNode Services.scriptSecurityManager.getSystemPrincipal(), @@ -1044,7 +1091,7 @@ export class WebSocketConnection { } // Returns a promise that resolves when the websocket channel is opened. open(url) { - this._ws = WebSocketConnection.makeWebSocketChan(); + this._ws = WebSocketConnection.makeWebSocketChan(url); let uri = Services.io.newURI(url); this._ws.asyncOpen(uri, url, {}, 0, this, null); return this._openPromise; diff --git a/netwerk/test/unit/test_websocket_server.js b/netwerk/test/unit/test_websocket_server.js @@ -9,6 +9,7 @@ /* import-globals-from head_channels.js */ const { + NodeWebSocketPlainServer, NodeWebSocketServer, NodeWebSocketHttp2Server, NodeHTTPProxyServer, @@ -66,6 +67,41 @@ async function channelOpenPromise(url, msg) { } // h1.1 direct +async function test_h1_plain_websocket_direct() { + let wss = new NodeWebSocketPlainServer(); + await wss.start(); + registerCleanupFunction(async () => wss.stop()); + Assert.notEqual(wss.port(), null); + await wss.registerMessageHandler((data, ws) => { + ws.send(data); + }); + let url = `ws://localhost:${wss.port()}`; + const msg = "test websocket"; + + let conn = new WebSocketConnection(); + await conn.open(url); + conn.send(msg); + let mess1 = await conn.receiveMessages(); + Assert.deepEqual(mess1, [msg]); + + // Now send 3 more, and check that we received all of them + conn.send(msg); + conn.send(msg); + conn.send(msg); + let mess2 = []; + while (mess2.length < 3) { + // receive could return 1, 2 or all 3 replies. + mess2 = mess2.concat(await conn.receiveMessages()); + } + Assert.deepEqual(mess2, [msg, msg, msg]); + + conn.close(); + let { status } = await conn.finished(); + + Assert.equal(status, Cr.NS_OK); +} + +// h1.1 direct async function test_h1_websocket_direct() { let wss = new NodeWebSocketServer(); await wss.start(); @@ -416,6 +452,7 @@ async function test_websocket_fallback() { checkConnectionActivities(observer.activites, "localhost", wss.port()); } +add_task(test_h1_plain_websocket_direct); add_task(test_h1_websocket_direct); add_task(test_h2_websocket_direct); add_task(test_h1_ws_with_secure_h1_proxy); diff --git a/testing/xpcshell/moz-http2/moz-http2.js b/testing/xpcshell/moz-http2/moz-http2.js @@ -1546,9 +1546,6 @@ function forkProcessInternal(forked) { } if (Object.keys(forked.messageHandlers).length === 0) { - console.log( - `child process ${id} closing code: ${code} signal: ${signal}` - ); return; }