/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
/* import-globals-from head_cache.js */
/* import-globals-from head_cookies.js */
/* import-globals-from head_channels.js */
/* import-globals-from head_servers.js */
/* import-globals-from head_websocket.js */
var CC = Components.Constructor;
const ServerSocket = CC(
"@mozilla.org/network/server-socket;1",
"nsIServerSocket",
"init"
);
let certdb = Cc[
"@mozilla.org/security/x509certdb;1"].getService(
Ci.nsIX509CertDB
);
add_setup(() => {
Services.prefs.setBoolPref(
"network.http.http2.websockets",
true);
});
registerCleanupFunction(() => {
Services.prefs.clearUserPref(
"network.http.http2.websockets");
});
// TLS handshake to the end server fails - no proxy
async
function test_tls_fail_on_direct_ws_server_handshake() {
// no cert and no proxy
let wss =
new NodeWebSocketServer();
await wss.start();
registerCleanupFunction(async () => {
await wss.stop();
});
Assert.notEqual(wss.port(),
null);
let chan = makeWebSocketChan();
let url = `wss:
//localhost:${wss.port()}`;
const msg =
"test tls handshake with direct ws server fails";
let [status] = await openWebSocketChannelPromise(chan, url, msg);
// can be two errors, seems to be a race between:
// * overwriting the WebSocketChannel status with NS_ERROR_NET_RESET and
// * getting the original 805A1FF3 // SEC_ERROR_UNKNOWN_ISSUER
if (status == 2152398930) {
Assert.equal(status, 0x804b0052);
// NS_ERROR_NET_INADEQUATE_SECURITY
}
else {
// occasionally this happens
Assert.equal(status, 0x804b0057);
// NS_ERROR_WEBSOCKET_CONNECTION_REFUSED
}
}
// TLS handshake to proxy fails
async
function test_tls_fail_on_proxy_handshake() {
// we have ws cert, but no proxy cert
addCertFromFile(certdb,
"http2-ca.pem",
"CTu,u,u");
let proxy =
new NodeHTTPSProxyServer();
await proxy.start();
let wss =
new NodeWebSocketServer();
await wss.start();
registerCleanupFunction(async () => {
await wss.stop();
await proxy.stop();
});
Assert.notEqual(wss.port(),
null);
let chan = makeWebSocketChan();
let url = `wss:
//localhost:${wss.port()}`;
const msg =
"test tls failure on proxy handshake";
let [status] = await openWebSocketChannelPromise(chan, url, msg);
// see above test for details on why 2 cases here
if (status == 2152398930) {
Assert.equal(status, 0x804b0052);
// NS_ERROR_NET_INADEQUATE_SECURITY
}
else {
Assert.equal(status, 0x804b0057);
// NS_ERROR_WEBSOCKET_CONNECTION_REFUSED
}
await proxy.stop();
}
// the ws server does not respond (closed port)
async
function test_non_responsive_ws_server_closed_port() {
// ws server cert already added in previous test
// no ws server listening (closed port)
let randomPort = 666;
// "random" port
let chan = makeWebSocketChan();
let url = `wss:
//localhost:${randomPort}`;
const msg =
"test non-responsive ws server closed port";
let [status] = await openWebSocketChannelPromise(chan, url, msg);
Assert.equal(status, 0x804b0057);
// NS_ERROR_WEBSOCKET_CONNECTION_REFUSED
}
// no ws response from server (ie. no ws server, use tcp server to open port)
async
function test_non_responsive_ws_server_open_port() {
// we are expecting the timeout in this test, so lets shorten to 1s
Services.prefs.setIntPref(
"network.websocket.timeout.open", 1);
// ws server cert already added in previous test
// use a tcp server to test open port, not a ws server
var server = ServerSocket(-1,
true, -1);
// port, loopback, default-backlog
var port = server.port;
info(
"server: listening on " + server.port);
server.asyncListen({});
// queue cleanup after all tests
registerCleanupFunction(() => {
server.close();
Services.prefs.clearUserPref(
"network.websocket.timeout.open");
});
// try ws connection
let chan = makeWebSocketChan();
let url = `wss:
//localhost:${port}`;
const msg =
"test non-responsive ws server open port";
let [status] = await openWebSocketChannelPromise(chan, url, msg);
Assert.equal(status, Cr.NS_ERROR_NET_TIMEOUT_EXTERNAL);
// we will timeout
Services.prefs.clearUserPref(
"network.websocket.timeout.open");
}
// proxy does not respond
async
function test_proxy_doesnt_respond() {
Services.prefs.setIntPref(
"network.websocket.timeout.open", 1);
Services.prefs.setBoolPref(
"network.http.http2.websockets",
false);
// ws cert added in previous test, add proxy cert
addCertFromFile(certdb,
"http2-ca.pem",
"CTu,u,u");
addCertFromFile(certdb,
"proxy-ca.pem",
"CTu,u,u");
info(
"spinning up proxy");
let proxy =
new NodeHTTPSProxyServer();
await proxy.start();
// route traffic through non-existant proxy
const pps = Cc[
"@mozilla.org/network/protocol-proxy-service;1"].getService();
let randomPort = proxy.port() + 1;
var filter =
new NodeProxyFilter(
proxy.protocol(),
"localhost",
randomPort,
0
);
pps.registerFilter(filter, 10);
registerCleanupFunction(async () => {
await proxy.stop();
Services.prefs.clearUserPref(
"network.websocket.timeout.open");
});
// setup the websocket server
info(
"spinning up websocket server");
let wss =
new NodeWebSocketServer();
await wss.start();
registerCleanupFunction(() => {
wss.stop();
});
Assert.notEqual(wss.port(),
null);
await wss.registerMessageHandler((data, ws) => {
ws.send(data);
});
info(
"creating and connecting websocket");
let url = `wss:
//localhost:${wss.port()}`;
let conn =
new WebSocketConnection();
conn.open(url);
// do not await, we don't expect a fully opened channel
// check proxy info
info(
"checking proxy info");
let proxyInfoPromise = conn.getProxyInfo();
let proxyInfo = await proxyInfoPromise;
Assert.equal(proxyInfo.type,
"https");
// let's be sure that failure is not "direct"
// we fail to connect via proxy, as expected
let { status } = await conn.finished();
info(
"stats: " + status);
Assert.equal(status, 0x804b0057);
// NS_ERROR_WEBSOCKET_CONNECTION_REFUSED
}
add_task(test_tls_fail_on_direct_ws_server_handshake);
add_task(test_tls_fail_on_proxy_handshake);
add_task(test_non_responsive_ws_server_closed_port);
add_task(test_non_responsive_ws_server_open_port);
add_task(test_proxy_doesnt_respond);