fetch verweigert Port 5060 -- und sagt dasselbe wie ein toter Server

Nach der Umstellung auf abgeleitete Nummern bekam pruef-chat-kanaele
die 5060 und stuerzte ab:

  TypeError: fetch failed

Der Server lief nachweislich ("Server laeuft auf http://127.0.0.1:5060"),
die Anmeldung ueber `http.request` hatte sogar geklappt, und BASIS war
sauber ("http://127.0.0.1:5060", 21 Zeichen, PORT eine Zahl). Nur die
`fetch`-Aufrufe scheiterten.

5060 ist SIP und steht auf der "bad ports"-Liste der
Fetch-Spezifikation. Node hat sie uebernommen: `fetch` baut dorthin
keine Verbindung auf, noch bevor ein Paket fliegt. Die Ursache steht
nur in `.cause` -- "bad port" statt "ECONNREFUSED". Die Meldung
obendrueber ist beide Male dieselbe, und wer sie liest, sucht am
Server.

Gegengeprueft mit einem echten Zuhoerer auf beiden Nummern:
  5060 -> fetch failed (bad port)
  5062 -> fetch failed (ECONNREFUSED)   <- also normal erreichbar

`eigenerPort` ueberspringt die gesperrten Nummern jetzt (portNummer).
Uebersprungen wird nach der REGEL, nicht nach einer Tabelle von
Sonderfaellen: die n-te brauchbare Nummer ab 5000. Eindeutig bleibt es,
weil die Reihenfolge feststeht.

pruef-portnummern (11 statt 8) prueft es doppelt: gegen die Liste UND
am echten Verhalten -- ein Zuhoerer auf 5060 muss fuer `fetch` tot
sein, einer auf einer abgeleiteten Nummer erreichbar. Ohne die zweite
Haelfte waere die Liste nur eine Behauptung ueber Node, und
Behauptungen altern.

Nebenbefund: Auch im alten, von Hand vergebenen Bereich lag eine
gesperrte Nummer -- die 4190. Sie war nie vergeben, rein zufaellig.

pruef-chat-kanaele: 79 Pruefungen, 0 Fehler -- wieder auf der
Grundlinie, die vor der Umstellung gemessen wurde.

Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
2026-09-20 23:06:52 +02:00
co-authored by Claude Opus 5
parent aa8842e72e
commit 445ea88f2b
2 changed files with 107 additions and 4 deletions
+58 -1
View File
@@ -134,6 +134,63 @@ const PRO_DATEI = 2;
* etwa weil jemand die Funktion aus einem anderen Ordner aufruft --,
* wird NICHT geraten. Eine geratene Nummer waere genau die Doppelung,
* die hier abgeschafft wird. */
/* =====================================================================
PORTS, DIE `fetch` NICHT ANFASST (20.09.2026, teuer gelernt)
Die Fetch-Spezifikation fuehrt eine Liste "bad ports" -- Nummern, auf
die ein Browser KEINE Verbindung aufbaut, weil sich ueber sie fremde
Dienste missbrauchen liessen (SMTP, NNTP, SIP, IRC und andere). Node
hat diese Liste uebernommen: `fetch` wirft dort `TypeError: fetch
failed` mit der Ursache `bad port`, noch bevor ein Paket fliegt.
WIE ES AUFGEFALLEN IST: Nach der Umstellung auf abgeleitete Nummern
bekam pruef-chat-kanaele die 5060 -- und stuerzte ab, obwohl der
Server nachweislich lief ("Server laeuft auf http://127.0.0.1:5060")
und die Anmeldung ueber `http.request` sogar geklappt hatte. Nur die
`fetch`-Aufrufe scheiterten. 5060 ist SIP und steht auf der Liste.
WARUM DAS SO SCHWER ZU FINDEN WAR: Die Meldung lautet "fetch failed"
-- dieselbe Meldung wie bei einem Server, der nicht laeuft. Wer sie
liest, sucht am Server. Der Unterschied steht erst in `.cause`:
`bad port` statt `ECONNREFUSED`. Gegengeprueft mit einem echten
Zuhoerer auf 5060: Port 5060 -> "bad port", Port 5062 -> sauberes
"ECONNREFUSED". Die Sperre ist also real und trifft genau diese
Nummern.
NEBENBEFUND: Auch im alten, von Hand vergebenen Bereich lag eine --
die 4190 (ManageSieve). Sie war nie vergeben, rein zufaellig.
===================================================================== */
const GESPERRT = new Set([
1, 7, 9, 11, 13, 15, 17, 19, 20, 21, 22, 23, 25, 37, 42, 43, 53, 69, 77, 79,
87, 95, 101, 102, 103, 104, 109, 110, 111, 113, 115, 117, 119, 123, 135, 137,
138, 139, 143, 161, 179, 389, 427, 465, 512, 513, 514, 515, 526, 530, 531,
532, 540, 548, 554, 556, 563, 587, 601, 636, 989, 990, 993, 995, 1719, 1720,
1723, 2049, 3659, 4045, 4190, 5060, 5061, 6000, 6566, 6665, 6666, 6667, 6668,
6669, 6679, 6697, 10080,
]);
/** Die n-te brauchbare Nummer ab BASIS -- gesperrte werden uebersprungen.
*
* Damit bleibt die Ableitung eindeutig (die Reihenfolge steht fest),
* ohne dass eine gesperrte Nummer je herauskommt. Eine Liste von
* Ausnahmen musste dafuer niemand pflegen: Uebersprungen wird nach
* der Regel, nicht nach einer Tabelle von Sonderfaellen.
*/
export function portNummer(nte) {
let p = BASIS;
let uebrig = nte;
while (true) {
if (!GESPERRT.has(p)) {
if (uebrig === 0) return p;
uebrig -= 1;
}
p += 1;
if (p > BASIS + 5000) {
throw new Error("[Port] Kein freier Nummernbereich mehr oberhalb von " + BASIS + ".");
}
}
}
export async function eigenerPort(meta, wer = null, nr = 0) {
const pfad = fileURLToPath(meta.url);
const mein = basename(pfad);
@@ -151,5 +208,5 @@ export async function eigenerPort(meta, wer = null, nr = 0) {
if (nr < 0 || nr >= PRO_DATEI) {
throw new Error(`[Port] Es gibt ${PRO_DATEI} Nummern je Datei (0 und 1), nicht ${nr}.`);
}
return portMussFreiSein(BASIS + stelle * PRO_DATEI + nr, wer || mein.replace(/\.mjs$/, ""));
return portMussFreiSein(portNummer(stelle * PRO_DATEI + nr), wer || mein.replace(/\.mjs$/, ""));
}