Ein turn: ohne Zugangsdaten haette JEDEN Anruf verhindert, nicht nur die vermittelten
Gefunden am 25.09.2026 beim Bau des Podcast-Studios, das dieselbe
Rechnung benutzt, und dort im echten Browser gemessen:
Failed to construct 'RTCPeerConnection': Both username and credential
are required when the URL scheme is "turn" or "turns".
`new RTCPeerConnection(...)` WIRFT. Die Folge ist nicht "kein
Vermittlungsserver", sondern KEIN ANRUF -- auch nicht der, der direkt
zustande gekommen waere. Aus einem Randproblem (etwa jeder Fuenfte
braucht Vermittlung) waere ein Totalausfall fuer alle geworden,
ausgeloest davon, dass /etc/coturn-workspace.geheimnis einmal nicht
lesbar ist: Rechte verstellt, beim Neuaufbau vergessen, Datei leer.
server/workspace-turn.js laesst solche Eintraege bewusst stehen, damit
der Grund nicht verschwindet ("KEIN STILLES WEGLASSEN"). Das ist dort
richtig -- es heisst aber, dass im Browser aussortiert werden muss,
bevor die Verbindung gebaut wird. Genau das fehlte. Der Kommentar
daneben behauptete "ein turn: ohne Passwort schadet nicht"; das war
nie gemessen und ist falsch.
Zwei Aenderungen in workspace/assets/js/anruf.js:
1. Beim Uebernehmen der Adressen werden turn:/turns:-Eintraege ohne
Benutzer UND Passwort aussortiert. STUN bleibt -- es kennt gar keine
Anmeldung und ist der Weg, der in den meisten Faellen reicht. Der
Grund geht nicht verloren, er steht weiter in der Konsole (jetzt mit
dem Dateinamen, in dem man nachsehen muss).
2. `adressenFrisch()` sagt bei gesetztem Grund immer "nicht frisch".
Sonst waere die Liste fuer immer frisch: Ohne Zugangsdaten bleibt nur
STUN uebrig, und ein STUN-Eintrag hat keinen Ablaufzeitpunkt --
`every()` sagt dann "alles gueltig" und es wird nie wieder gefragt.
Waere die Datei auf dem Server repariert, telefonierte trotzdem
niemand mehr mit Vermittlung, bis er die Seite neu laedt. (Nebenbei
die zweite Falle derselben Zeile: `every()` auf einer LEEREN Liste
ist `true`.)
Geprueft in server/pruef-anruf.mjs: Die Pruefung liest den Filter aus
der ausgelieferten Datei und FUEHRT IHN AUS -- vier Adressen hinein,
zwei brauchbare heraus, mit Gegenprobe, dass er ueberhaupt etwas
wegnimmt. Eine Pruefung, die nur nachsieht, ob irgendwo "filter" steht,
waere auch dann gruen, wenn der Filter das Falsche tut.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
+54
-1
@@ -16,7 +16,7 @@
|
||||
|
||||
Aufrufen mit: node server/pruef-anruf.mjs
|
||||
===================================================================== */
|
||||
import { mkdtempSync, rmSync, writeFileSync, unlinkSync } from "node:fs";
|
||||
import { mkdtempSync, rmSync, writeFileSync, unlinkSync, readFileSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { request as httpAnfrage } from "node:http";
|
||||
@@ -1224,6 +1224,59 @@ melde("=== 8. Zu dritt ===");
|
||||
}
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
EIN turn: OHNE ZUGANGSDATEN DARF DEN BROWSER NICHT ERREICHEN
|
||||
(25.09.2026)
|
||||
|
||||
Am selben Tag beim Bau des Podcast-Studios im echten Browser
|
||||
nachgemessen:
|
||||
|
||||
Failed to construct 'RTCPeerConnection': Both username and
|
||||
credential are required when the URL scheme is "turn" or "turns".
|
||||
|
||||
`new RTCPeerConnection(...)` WIRFT. Die Folge ist nicht "kein
|
||||
Vermittlungsserver", sondern KEIN ANRUF -- auch nicht der, der direkt
|
||||
zustande gekommen waere. Aus einem Randproblem (etwa jeder Fuenfte
|
||||
braucht Vermittlung) wuerde ein Totalausfall fuer alle, ausgeloest
|
||||
davon, dass eine Datei auf dem Server unlesbar ist.
|
||||
|
||||
Der Server laesst solche Eintraege bewusst stehen, damit der Grund
|
||||
nicht verschwindet -- das ist dort richtig. Aussortiert wird im
|
||||
Browser, in `workspace/assets/js/anruf.js`.
|
||||
|
||||
DIESE PRUEFUNG LIEST KEINEN TEXT, SONDERN FUEHRT DEN ECHTEN AUSDRUCK
|
||||
AUS. Eine Prüfung, die nur nachsieht, ob irgendwo das Wort "filter"
|
||||
steht, waere auch dann gruen, wenn der Filter das Falsche tut.
|
||||
===================================================================== */
|
||||
{
|
||||
const quelle = readFileSync(new URL("../workspace/assets/js/anruf.js", import.meta.url), "utf8");
|
||||
const t = /adressen = \(d\.adressen \|\| \[\]\)(\.filter\([\s\S]*?\n {8}\}\);)/.exec(quelle);
|
||||
ok(!!t, "in anruf.js wird die Adressliste ueberhaupt gefiltert");
|
||||
if (t) {
|
||||
/* Genau der Ausdruck aus der ausgelieferten Datei, ausgefuehrt. */
|
||||
const filtern = new Function("d", "return (d.adressen || [])" + t[1] + ";");
|
||||
const rein = {
|
||||
adressen: [
|
||||
{ urls: "stun:1.2.3.4:3478" },
|
||||
{ urls: "turn:1.2.3.4:3478?transport=udp", username: "1:a", credential: "x" },
|
||||
{ urls: "turn:1.2.3.4:3478?transport=tcp" },
|
||||
{ urls: "turns:1.2.3.4:5349", username: "1:a" },
|
||||
],
|
||||
};
|
||||
const raus = filtern(rein);
|
||||
ok(raus.length === 2, `es bleiben genau die zwei brauchbaren uebrig (${raus.length})`);
|
||||
ok(raus.some((a) => a.urls.startsWith("stun:")),
|
||||
"STUN bleibt drin -- es kennt gar keine Anmeldung und reicht meistens");
|
||||
ok(raus.every((a) => !/^turns?:/.test(a.urls) || (a.username && a.credential)),
|
||||
"kein turn: ohne Benutzer UND Passwort geht hinaus");
|
||||
/* GEGENPROBE: Wuerde der Filter alles durchlassen, waere die Zeile
|
||||
oben auch gruen. Hier wird bewiesen, dass er wirklich etwas
|
||||
wegnimmt. */
|
||||
ok(raus.length < rein.adressen.length,
|
||||
"Gegenprobe: der Filter nimmt tatsaechlich etwas weg");
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
melde("");
|
||||
melde(`${geprueft} Pruefungen, ${fehler} Fehler`
|
||||
|
||||
Reference in New Issue
Block a user