feat(core): Gnutella search and download after Java, measured against Java

GnutellaRun adds a line of four peers: a search goes on as a query, each
peer answers with a hit for each matching file and the hits come back the
way the query came; a hit's file is fetched by HTTP on port 6346. The
file type names of the model move from the project export and import into
the core, so that the download uses them too.

Departures from Java: a peer that sent hits keeps its connection, so that
the hits of farther peers come back too (Java closes it and loses them),
and sizes are in characters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 14:59:26 +00:00
co-authored by Claude Opus 5.5
parent b4a95e6cac
commit ce5b10c1f3
13 changed files with 39934 additions and 130 deletions
+3 -3
View File
@@ -27,7 +27,7 @@ Swift-Pfade relativ zu `filius-ipad/ios/FiliusPad/TopologyEditor/` (Stand
| `src/runtime/apps/emailServer.ts` | Java `EmailServer`, `SMTPServer`, `SMTPMitarbeiter`, `POP3Server`, `POP3Mitarbeiter`, `EmailKonto` | neu nach Java (F3.3a): Konten einer Domain, SMTP auf Port 25 speichert Mails an eigene Konten (wie Java neu gelesen) und schickt bei unbekannten Empfängern eine Benachrichtigung an einen Absender der Domain, POP3 auf Port 110 gibt Mails ab 0 nummeriert aus; beide zusammen ein- und ausgeschaltet, POP3 zuerst; SMTP-Antworten in der Sprache des Projekts; Fensterzeilen wie Java. An Java-Filius gemessen (`EmailRun`, `MailCases`). Abweichend von Java: nach einer Mail ist der Umschlag neu (Java antwortet dem nächsten Befehl 503 und behält Absender, Empfänger und Text); ein Befehl, den der Zustand nicht nimmt, bekommt 503 (Java schweigt), HELO beginnt neu; in DATA ist alles Text, auch `quit`; die Domain gilt in jeder Schreibweise; ein Empfänger ohne `@` ist unbekannt, ein leerer Absender bekommt keine Benachrichtigung (Java wirft), eine Benachrichtigung an eine Mail ohne From geht an den Absender des Umschlags (Java: `To: null`); POP3: eine Mail lässt sich mehrmals abrufen, eine fehlende Mail, `LIST` ohne Mails und falsche Argumente geben `-ERR` (Java: leere Mail, leere Antwort, Abbruch), `LIST n` listet die eine Mail, Nummern bleiben nach `DELE` (Javas `LIST` zählt neu), vor der Anmeldung `-ERR unknown command`, `QUIT` immer `+OK`. Seit F3.3b leitet der Server Mails an fremde Domains per MX weiter (in seinem eigenen Thread, je Weiterleitung ein neuer SMTP-Client) und schickt eine Benachrichtigung an einen fremden Absender mit leerem Absender an dessen Domain. Noch nicht: die Kontodatei `/mailserver/konten.txt` zur Laufzeit |
| `src/runtime/apps/emailClient.ts` | Java `EmailAnwendung`, `SMTPClient`, `POP3Client`, das Senden aus `GUIApplicationEmailAnwendungWindow` | neu nach Java (F3.3b): das E-Mail-Programm sendet eine Mail an den SMTP-Server seines Kontos, eine Verbindung je Empfänger (An, Cc, Bcc), und holt die Mails seines Kontos vom POP3-Server (jede abgerufen, dann gelöscht); die Prüfungen des Fensters (kein Konto, Adresse, die Javas Muster nicht nimmt, kein Empfänger); Meldungen wie Javas Beobachter (Verbindung, versendet, getrennt, Ausnahmen); der SMTP-Client dient auch dem Server zum Weiterleiten. An Java-Filius gemessen (`EmailClientRun`). Abweichend von Java: der SMTP-Port des Kontos gilt (Java verbindet immer zu 25); drei SYN statt einem |
| `src/runtime/apps/filePrograms.ts` | Java `FileExplorer`, `TextEditor`, `ImageViewer` und ihre Fenster, `config/filetypes.txt`, die Meldungen `sw_fileexplorer_msg1`–`3`, `fileexplorer_msg19` | neu nach Java (F3.5b): die Dateioperationen hinter den Knöpfen von Datei-Explorer (Ordnerliste, neuer Ordner, löschen, kopieren/ausschneiden/einfügen, umbenennen, importieren), Texteditor (speichern, speichern unter) und Bildbetrachter, auf den Dateien des Knotens; an Java-Filius gemessen (`FileCases`). Abweichend von Java: ein Ordnername, der zu keinem Namen wird, legt nichts an; Einfügen auf einen vorhandenen Namen wird abgelehnt (Java: zweiter Eintrag gleichen Namens); Umbenennen auf einen Namen mit `/` oder mit Leerzeichen am Rand wird abgelehnt, eine reine Änderung der Groß-/Kleinschreibung ausgeführt (Java lehnt sie ab); „Speichern unter“ und Import auf einen Ordnernamen werden abgelehnt (Java wirft); die Größe einer Textdatei sind ihre Zeichen |
| `src/runtime/apps/gnutella.ts` | Java `filius.software.dateiaustausch` (`PeerToPeerAnwendung`, `PeerToPeerServer`, `PeerToPeerServerMitarbeiter`, `PeerToPeerClient`, `PeerToPeerClientMitarbeiter`, `PingPaket`, `PongPaket`) | neu nach Java (F3.6a): Beitreten mit Ping und Pong in Javas Textformat über Port 6346, Weiterleiten an die eigenen Teilnehmer, Pongs auf dem Weg des Pings zurück, Höchstzahl der Teilnehmer, Zurücksetzen, Ordner `/peer2peer`; an Java-Filius gemessen (`GnutellaRun`). Die Swift-Fassung (`TopologyRuntimeGnutella.swift`, eigenes Protokoll) nicht übernommen. Abweichend von Java: ein zweites Mal ankommender Ping bekommt keinen Pong, und seine Verbindung bleibt (Java wirft und schließt sie) |
| `src/runtime/apps/gnutella.ts` | Java `filius.software.dateiaustausch` (`PeerToPeerAnwendung`, `PeerToPeerServer`, `PeerToPeerServerMitarbeiter`, `PeerToPeerClient`, `PeerToPeerClientMitarbeiter`, `PingPaket`, `PongPaket`) | neu nach Java (F3.6a): Beitreten mit Ping und Pong in Javas Textformat über Port 6346, Weiterleiten an die eigenen Teilnehmer, Pongs auf dem Weg des Pings zurück, Höchstzahl der Teilnehmer, Zurücksetzen, Ordner `/peer2peer`; an Java-Filius gemessen (`GnutellaRun`). Die Swift-Fassung (`TopologyRuntimeGnutella.swift`, eigenes Protokoll) nicht übernommen. Seit F3.6b Suche mit Query und Treffern (weitergeleitet wie Pings, Treffer auf dem Weg der Query zurück), Ergebnisse, Download per HTTP über 6346 (`QueryPaket`, `QueryHitPaket`, `httpAnfrageVerarbeiten`, `herunterladenDatei`). Abweichend von Java: ein zweites Mal ankommender Ping bekommt keinen Pong, und seine Verbindung bleibt (Java wirft und schließt sie); wer Treffer geschickt hat, hält die Verbindung, damit auch die Treffer der weiter entfernten Teilnehmer zurückkommen (Java schließt sie, die gehen verloren); Größen in Treffer und Pong in Zeichen (Java: Base64-dekodiert) |
| `src/runtime/apps/terminal.ts`, `src/runtime/apps/terminalTexts.ts` | Java `filius.software.lokal.Terminal`, die Eingabe aus `GUIApplicationTerminalWindow`, die Texte `sw_terminal_*` und `terminal_msg*` des Bündels | neu nach Java (F3.4a): die Befehlszeile mit Javas Zerlegung der Eingabe, Verteilung nach dem Befehlsnamen und den lokalen Befehlen `ls`/`dir`, `cd`, `pwd`, `mkdir`, `touch`, `cp`/`copy`, `mv`/`move`, `rm`/`del`, `cat`/`type`, `test`, `help`, `ipconfig`, `route`; Texte in der Sprache des Projekts, aus dem von Java geladenen Bündel erzeugt. An Java-Filius gemessen (`TerminalCases`). Abweichend von Java: die Größe einer Textdatei sind ihre Zeichen (Java dekodiert Base64); ein fehlender Ordner ist für `ls` „nicht vorhanden“, `ls /` nennt die Wurzel; `cd` auf eine Datei, `touch`/`mkdir` in fehlenden Ordnern und `cp` auf einen Ordnernamen scheitern; `..` bleibt an der Wurzel; `rm` und `mv` nehmen absolute Pfade absolut, die Wurzel ist nicht löschbar, nach dem Löschen des Arbeitsordners gilt der nächste verbliebene darüber; `mv` auf die Datei selbst benennt sie um. Seit F3.4b die Netzbefehle `ping` (Strg+C über `interrupt`), `host`, `nslookup`, `arp` und `netstat`, mit Javas Laufmarken; ein unbekannter Befehl wird wie bei Java sofort gemeldet, auch während ein anderer läuft; seit F3.4c `traceroute` und `tcpdump` (`arpsend` nicht gebaut, der Befehl ist unbekannt); an Java-Filius gemessen (`TerminalRun`). Abweichend von Java: `ping` nennt den Host, wo Java seinen ersten Parameter nennt (`-b` in der Statistik), und nimmt vor dem Host nur `-b` (Java nimmt jedes Wort und pingt einen Broadcast); `arp` und `netstat` listen in der Reihenfolge des Lernens bzw. Anlegens (Java: Reihenfolge einer `HashMap`); `netstat` zeigt von einem UDP-Server nur den lauschenden Socket (Java auch einen für jede je beantwortete Adresse, nie geschlossen); `traceroute` sagt sein Fazit vor der Endmarke (Java danach, wo sein Fenster keinen Text mehr zeigt) und nennt ein Ziel beim 20. Sprung erreicht (Java: nicht erreicht); `tcpdump` meldet jeden Frame sofort (Java schaut alle 100 ms) |
| `src/runtime/apps/echo.ts` | Java `filius.software.clientserver` (`ServerBaustein`, `ServerBausteinMitarbeiter`, `ClientAnwendung`, `ClientBaustein`) | neu nach Java statt nach Swift (F3.1): Echo-Server (auf `server.ts`, sendet jede Nachricht zurück) und einfacher Client (verbinden über Adresse oder Namen, senden, empfangen, trennen), mit Javas Fensterzeilen. An Java-Filius gemessen. Abweichend von Java: Der Server merkt das Ausschalten, der Client die Verbindung sofort (Java alle 100 ms); ohne Route scheitert der Client sofort (Java wartet ewig ohne Meldung); ausgeschaltet bestätigt der Server noch das FIN seiner Verbindungen (Java gibt den Port frei, das FIN bleibt unbeantwortet) |
| `src/runtime/dns.ts` | Java `filius.software.dns.DNSNachricht`, `Query`, `ResourceRecord` | neu nach Java statt nach Swift (Swift ersetzt Javas Textnachrichten durch `FILIUS-DNS-TYPED/1`): Kopfzeile `ID=… QR=… RCODE=… QDCOUNT=… …`, Frage- und Eintragszeilen, Suche nach Namen ohne Rücksicht auf Groß- und Kleinschreibung, NS der längsten Zone, sonst der Wurzel |
@@ -42,7 +42,7 @@ Swift-Pfade relativ zu `filius-ipad/ios/FiliusPad/TopologyEditor/` (Stand
| `src/runtime/capture.ts` | Java `filius.rahmenprogramm.nachrichten.Lauscher` | neu nach Java (Swift hat stattdessen die Paketspur je Schritt): der Mitschnitt je Netzwerkkarte, jeder gesendete und empfangene Frame einmal mit Zeit und Nummer, wie Java auch Frames an andere Karten und solche, die die Firewall verwirft; Switches ohne Liste; verlorene Frames getrennt; bleibt über Stopp und Neustart, geleert nur auf Wunsch. Abweichend von Java: je Port statt je MAC-Adresse (Java legt zwei Karten mit gleicher MAC zusammen) und höchstens 10.000 Frames je Karte, die ältesten 1.000 fallen auf einmal heraus, die Nummern bleiben (Java behält alles) |
| `src/util/equal.ts` | — | neu (Ersatz für Swifts `Equatable`) |
| `src/util/swiftString.ts` | — | neu: Swift-String-Verhalten, das der übertragene Code stillschweigend voraussetzt (Trimmen, Kleinschreibung je Skalar, kanonische Gleichheit, Sortierung nach Skalarwerten, Base64 wie Foundation); am Swift-Orakel gemessen, Leerraum und Steuerzeichen über ganz Unicode |
| `src/model/virtualFileSystem.ts`, `src/model/defaultImages.ts` | `State/TopologyVirtualFileSystem.swift` | übertragen; Schlüssel in NFC statt Swifts kanonischer Wörterbuch-Gleichheit; Steuerzeichen nach Unicode Cc+Cf, ohne Foundations Tabellenfehler in Ebene 14; seit F3.4a die Einträge eines Ordners auch in der Reihenfolge ihres Entstehens, wie Javas Dateibaum (`entriesInCreationOrder`); seit F3.5b `renameInPlace`: ein Eintrag behält beim Umbenennen seine Stelle, auch bei reiner Änderung der Groß-/Kleinschreibung, wie Javas Knoten (`renameItem` bleibt Swifts Verschieben) |
| `src/model/virtualFileSystem.ts`, `src/model/defaultImages.ts` | `State/TopologyVirtualFileSystem.swift` | übertragen; Schlüssel in NFC statt Swifts kanonischer Wörterbuch-Gleichheit; Steuerzeichen nach Unicode Cc+Cf, ohne Foundations Tabellenfehler in Ebene 14; seit F3.4a die Einträge eines Ordners auch in der Reihenfolge ihres Entstehens, wie Javas Dateibaum (`entriesInCreationOrder`); seit F3.5b `renameInPlace`: ein Eintrag behält beim Umbenennen seine Stelle, auch bei reiner Änderung der Groß-/Kleinschreibung, wie Javas Knoten (`renameItem` bleibt Swifts Verschieben); seit F3.6b `javaFileTypeName` und `fileContentOfJavaType` (Javas Dateityp aus der Art und zurück), aus Export und Import von `packages/fls` hierher, damit auch der Gnutella-Download sie nutzt |
| `test/virtualFileSystem.test.ts`, `test/vfs.*.json` | `TopologyProjectPersistenceTests.swift`, `TopologyEditorReducerTests.swift` (drei Dateisystem-Tests, als Fälle) | übertragen und erweitert: 11 Fälle, Ergebnis aus dem Swift-Kern |
| `test/strings.test.ts`, `test/strings.*.json` | — | neu: Fälle und ganze Zeichenmengen, Ergebnis aus dem Swift-Kern |
| `test/engine.test.ts` | `TopologyNetworkRuntimeEngineTests.swift` (21 von 72 Tests) | übertragen; `nextInt`- und `nextDouble`-Referenzwerte an OpenJDK 21 gemessen; die DHCP-Client-Tests seit F2.3b nach Javas Verhalten (neun, davon zwei benannte Java-Fehler, die der Kern nicht übernimmt); seit F2.8a sechs Tests für den Mitschnitt (über Neustart, Leeren, Obergrenze, verlorene Frames, Switches) |
@@ -62,7 +62,7 @@ Swift-Pfade relativ zu `filius-ipad/ios/FiliusPad/TopologyEditor/` (Stand
| `test/emailClientJava.test.ts`, `test/scenarios/email-client-java-*.java.json` | — | neu (F3.3b): sechs Abläufe mit dem E-Mail-Programm und zwei Servern gegen Java-Filius (`EmailClientRun`): senden mit Weiterleitung, abholen, Server per Name und Benachrichtigungen von beiden Servern, falsches Passwort, kein Server, unbekannter Servername; je Karte Frames, Zeiten, Tabellen, die Meldungen von Programm und Servern, Posteingang, Gesendete und Konten am Ende; Javas 100-ms-Blick kostet je Verbindung (und je DNS-Antwort, auf die es so wartet) eine Periode Toleranz; ein benannter Java-Fehler (nur ein SYN); bei `byName` die Startnummern ohne die Million (Thread-Wettlauf in Java) |
| `test/emailClient.test.ts` | — | neu (F3.3b): was das Fenster ablehnt, Bcc, der SMTP-Port des Kontos, eine ungültige Kontoadresse, eine Verbindung, die beim Warten endet, eine Mail ohne Absender aus dem Modell, die Ordner im Schnappschuss |
| `test/filePrograms.test.ts`, `test/file-programs.cases.txt`, `test/file-programs.{de,en}.java.json` | — | neu (F3.5b): sechs Fälle der Dateiprogramme gegen Java-Filius (`FileCases`), je Schritt Rückgabe und alle Dateien, Deutsch und Englisch, benannte Java-Fehler (`JAVA_BUGS`); dazu Dateitypen, Ordnerliste, Bildbetrachter, leerer Ordnername |
| `test/gnutellaJava.test.ts`, `test/gnutella.test.ts`, `test/scenarios/gnutella-java-*.java.json` | — | neu (F3.6a): sechs Abläufe des Beitretens gegen Java-Filius (`GnutellaRun`), je Karte die Frames samt Tabellen (wo viele Verbindungen zugleich laufen: je Verbindung und Richtung mit ihren Daten), die Teilnehmer jedes Programms mit Zeit; Javas GUIDs ersetzen die gezogenen, damit Längen und Sequenznummern gleich bleiben; dazu Paketformat, doppelter Ping, Kopf ohne Paket, Lebensdauer, Dateien im Pong |
| `test/gnutellaJava.test.ts`, `test/gnutella.test.ts`, `test/scenarios/gnutella-java-*.java.json` | — | neu (F3.6a, F3.6b): sechs Abläufe des Beitretens und zwei der Suche mit Download gegen Java-Filius (`GnutellaRun`), Ergebnisse und Dateien am Ende, je Karte die Frames samt Tabellen (wo viele Verbindungen zugleich laufen: je Verbindung und Richtung mit ihren Daten), die Teilnehmer jedes Programms mit Zeit; Javas GUIDs ersetzen die gezogenen, damit Längen und Sequenznummern gleich bleiben; dazu Paketformat, doppelter Ping, Kopf ohne Paket, Lebensdauer, Dateien im Pong |
| `test/terminal.test.ts`, `test/terminal.cases.txt`, `test/terminal.{de,en}.java.json` | — | neu (F3.4a): 16 Fälle der Befehlszeile gegen Java-Filius (`TerminalCases`), je Zeile die Handlung des Fensters, was das Programm sagt, Arbeitsordner und alle Dateien, Deutsch und Englisch; Javas Größe von Textdateien überall als Java-Fehler korrigiert, dazu acht Fälle mit benannten Java-Fehlern (`JAVA_BUGS`); ein Bild bleibt beim Kopieren ein Bild; jeder Text der Tabelle ist wörtlich Javas |
| `test/terminalJava.test.ts`, `test/scenarios/terminal-net.scenario.json`, `test/scenarios/terminal-java-*.java.json` | — | neu (F3.4b): zwölf Abläufe der Netzbefehle gegen Java-Filius (`TerminalRun`) auf einem LAN mit DNS-Server, Router und Rechner dahinter: `ping` im LAN, über den Router, ins Leere, hinter dem Router unerreichbar, ohne Route am Router, Broadcast, eigene Adresse, Fehler, Strg+C; `host` und `nslookup`, auch ohne erreichbaren DNS-Server; `arp`; `netstat` mit TCP-Verbindung und DNS-Server; je Karte die Frames samt Javas Tabellen, je Rechner Texte und Laufmarken mit Zeit; benannte Java-Fehler (`JAVA_BUGS`); die Reihenfolge der Antworten auf einen Broadcast ist ein Wettlauf von Javas Threads (je Sekunde als Menge verglichen); seit F3.4c neun Abläufe mit `traceroute` (LAN, über den Router, unerreichbar, ohne Route, ins Leere, eigene Adresse, Fehler, Strg+C) und `tcpdump` auf zwei Rechnern; ein Wächter verwirft Aufnahmen, in denen Java sein Aufwecken verpasst hat; dazu zehn Einzelfälle (traceroute über 20 Sprünge, Strg+C vor dem Start, fremde Echo-Antworten, gerundeter Verlust, Broadcast bei anderer Maske, zufälliger Identifier und sein Weiterzählen, gleich lange Routen) |
| `test/apps.test.ts` | — | neu (F3.1): wie Threads aufwachen (nach dem Ereignis, nach einer Pause hinter den anderen, ein Weckruf nur für sein Warten, Reihenfolge des Beginns, kein Warten auf schon Geltendes), und was die Java-Abläufe nicht zeigen: belegter Port, Name über DNS und ohne DNS, keine Route, unbestätigtes Senden, Neustart, eine Nachricht vor dem Schließen |