Version 2.8.15: Probe der Strecke, Grund aus _fail, RFB 3.3

This commit is contained in:
alientim committed 2026-09-13 12:04:51 +02:00
1 parent f551ce0ee6
commit ec5cbb2e17
2 files changed
+80 -27

No files matched your search

@@ -23,13 +23,38 @@ import RFB from "../vendor/novnc/core/rfb.js";
// der angemeldete Weg der bessere.
const OHNE_ZUGANGSDATEN = new Set([1]);
// Der Eingriff sitzt in einer privaten Methode der mitgelieferten Bibliothek.
// Das ist bewusst hier und nicht in der Bibliothek selbst: eine neue Fassung
// von noVNC laesst sich dann austauschen, ohne eine Aenderung nachzupflegen --
// faellt die Methode weg, greift die Vorauswahl nicht mehr, und die Sitzung
// laeuft wieder wie ohne sie. Kein stiller Bruch.
// Drei Eingriffe in private Methoden der mitgelieferten Bibliothek. Bewusst
// hier und nicht in der Bibliothek selbst: eine neue Fassung von noVNC laesst
// sich dann austauschen, ohne eine Aenderung nachzupflegen -- faellt eine
// Methode weg, greift der jeweilige Eingriff nicht mehr, und die Sitzung
// laeuft wieder wie ohne ihn. Kein stiller Bruch.
const istUnterstuetzt = RFB.prototype._isSupportedSecurityType;
// Den *Grund* eines Fehlschlags kennt nur ``_fail`` -- das Ereignis
// "disconnect" traegt ihn nicht, und der Weg ueber die Protokollausgabe
// funktioniert nicht: die Bibliothek bindet ``console.error`` beim Laden, also
// bevor eine Seite etwas daran aendern koennte. (Genau daran ist der erste
// Versuch gescheitert -- die Meldung blieb leer.)
let letzterGrund = "";
const originalFail = RFB.prototype._fail;
RFB.prototype._fail = function (details) {
letzterGrund = String(details);
return originalFail.call(this, details);
};
// Und der Abschluss der Leitung selbst: der Schliesscode sagt, ob TESM
// abgewiesen hat (1008), ob es ein Serverfehler war (1011) -- oder ob die
// Verbindung nie zustande kam (1006).
let letzterCode = 0;
const originalSocketClose = RFB.prototype._socketClose;
RFB.prototype._socketClose = function (ereignis) {
letzterCode = (ereignis && ereignis.code) || 0;
if (ereignis && ereignis.reason) {
letzterGrund = letzterGrund || String(ereignis.reason);
}
return originalSocketClose.call(this, ereignis);
};
const wurzel = document.getElementById("screen");
if (wurzel) {
starten(wurzel);
@@ -54,32 +79,16 @@ function starten(wurzel) {
);
let rfb = null;
let letzterFehler = "";
function melden(text, art = "") {
zeile.textContent = text;
zeile.className = `screen__status${art ? " screen__status--" + art : ""}`;
}
// noVNC meldet den *Grund* eines Fehlschlags ausschliesslich ins Protokoll
// der Entwicklerkonsole -- das Ereignis "disconnect" trägt ihn nicht. Ohne
// diesen Griff bliebe der Seite nur "Verbindung abgebrochen", und damit
// steht der Anwender genau dort, wo er ohne die ganze Anzeige auch stuende.
// Darum wird die Fehlerausgabe waehrend der Sitzung mitgelesen -- und
// hinterher wieder losgelassen.
const echteAusgabe = console.error.bind(console);
console.error = (...teile) => {
letzterFehler = teile.map((teil) => String(teil)).join(" ");
echteAusgabe(...teile);
};
window.addEventListener("beforeunload", () => {
console.error = echteAusgabe;
});
function grund() {
const teile = [];
if (letzterFehler) {
teile.push(letzterFehler.replace(/^Failed (when|while) \w+: /, ""));
if (letzterGrund) {
teile.push(letzterGrund.replace(/^Failed (when|while) \w+: /, ""));
}
if (rfb && rfb._rfbAuthScheme > 0) {
teile.push(`gewähltes Verfahren: ${rfb._rfbAuthScheme}`);
@@ -87,9 +96,35 @@ function starten(wurzel) {
return teile.join(" · ");
}
// Steht die WebSocket-Strecke zu TESM überhaupt? Zwei sehr verschiedene
// Ursachen sehen von aussen gleich aus: der VNC-Server mag nicht, oder die
// Verbindung kommt nie zustande, weil ein Proxy zwischen Browser und TESM
// "Upgrade" nicht durchreicht. Diese Probe trennt sie.
function streckeTesten() {
return new Promise((fertig) => {
let beantwortet = false;
const pruefling = new WebSocket(`${schema}//${window.location.host}/ws/probe`);
const schliessen = (ergebnis) => {
if (beantwortet) return;
beantwortet = true;
try {
pruefling.close();
} catch (fehler) {
/* schon zu */
}
fertig(ergebnis);
};
pruefling.onmessage = () => schliessen(true);
pruefling.onerror = () => schliessen(false);
pruefling.onclose = () => schliessen(false);
window.setTimeout(() => schliessen(false), 4000);
});
}
function verbinden(zugang) {
melden("Verbindung wird aufgebaut …");
letzterFehler = "";
letzterGrund = "";
letzterCode = 0;
// Vorauswahl nur, wenn wir nichts anzubieten haben: dann zaehlt der Weg,
// der ohne Zugangsdaten auskommt -- sofern der Server ihn anbietet.
@@ -136,10 +171,28 @@ function starten(wurzel) {
melden(
erklaerung
? `Verbindung abgebrochen – ${erklaerung}`
: "Verbindung abgebrochen, ohne dass der Client einen Grund nennt. " +
"Antwortet der VNC-Server noch?",
: "Verbindung abgebrochen. Wird geprüft, woran es liegt …",
"fehler",
);
// 1006 heisst: die Leitung ging zu, ohne dass die Gegenseite einen
// Grund geschickt hat -- typisch, wenn die WebSocket-Verbindung gar
// nicht erst zustande kam. Dann sagt die Probe, wer schweigt.
if (letzterCode === 1006 || !erklaerung) {
streckeTesten().then((steht) => {
melden(
steht
? `${erklaerung || "Verbindung abgebrochen"} – die WebSocket-Strecke zu ` +
"TESM selbst steht (Probe erfolgreich), der Abbruch kommt also von " +
"der VNC-Seite."
: "Die WebSocket-Verbindung zu TESM kommt nicht zustande – auch eine " +
"einfache Probe scheitert. Ein Proxy zwischen Browser und TESM muss " +
"die Kopfzeilen Upgrade und Connection durchreichen (nginx: " +
"location /ws/ mit proxy_set_header Upgrade $http_upgrade). Dasselbe " +
"gilt für die Browser-Konsole.",
"fehler",
);
});
}
}
rfb = null;
});