feat(core): the packet capture's table after Java's Lauscher, measured against Java's own tables

captureRows.ts builds Java's rows per frame (Lauscher.datenVorbereiten):
Ethernet; ARP, ICMP or IP; TCP or UDP; the data with Java's protocol
recognition; with addresses and ports or ports only. The comment stays
structured; captureCommentText says it with given words and numbers.

ScenarioNetwork writes Java's finished tables per card (Lauscher.getDaten,
German locale); all runtime runs are recorded again, NatRun has ttlOut.
expectSameCaptures compares both views for every frame. Fixed where the
engine differed: an ARP request's target MAC is the broadcast address,
an ICMP error's identifier and sequence number are 0 (RFC 792), and host
unreachable from a router carries the packet as forwarded. Not taken:
Java's lower-case broadcast address in a reply to 0.0.0.0, and the typo
'Exeeded'. RIP keeps its recordings: Java's staggered router start now
gives a different startup on this machine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-01 15:11:05 +00:00
co-authored by Claude Opus 5.5
parent 0a34f3a4c4
commit 21a404693c
55 changed files with 37423 additions and 1321 deletions
+4
View File
@@ -15,6 +15,7 @@
// forward 42.0.0.20 connects to 42.0.0.10:8080, forwarded to
// 192.168.0.10:80; sends, receives, closes
// pingWan 42.0.0.20 pings 42.0.0.10, then 192.168.0.10
// ttlOut 192.168.0.10 pings 42.0.0.20 with TTL 1: time exceeded
import filius.software.nat.NatEntry;
import filius.software.nat.NatGateway;
@@ -194,6 +195,9 @@ public class NatRun {
Thread.sleep(200);
tcpClient(SERVER, "42.0.0.10", 8080);
break;
case "ttlOut":
call("sendProbe 42.0.0.20", () -> icmp(os(LAN_PC).holeICMP().sendProbe("42.0.0.20", 1, 1, 1)));
break;
case "pingWan":
call("sendProbe 42.0.0.10", () -> icmp(os(SERVER).holeICMP().sendProbe("42.0.0.10", 64, 1, 1)));
call("sendProbe 192.168.0.10", () -> icmp(os(SERVER).holeICMP().sendProbe("192.168.0.10", 64, 1, 2)));
@@ -242,6 +242,32 @@ public class ScenarioNetwork {
out.close(']');
}
out.close('}');
writeRows(out, "rows", true);
writeRows(out, "layeredRows", false);
}
/**
* The packet capture's table of each card as FILIUS shows it
* (Lauscher.getDaten): with addresses and ports (`rows`, the data exchange
* window) or ports only (`layeredRows`, the layered view). Each row: number,
* source, destination, protocol, layer, comment — its time (the wall clock)
* left out.
*/
void writeRows(Json out, String key, boolean withAddresses) {
out.key(key).open('{');
for (Map.Entry<String, String> entry : macByNode.entrySet()) {
out.key(entry.getKey()).open('[');
for (Object[] row : Lauscher.getLauscher().getDaten(entry.getValue(), withAddresses, 1)) {
out.open('[');
for (int column = 0; column < row.length; column++) {
if (column == 1) continue;
out.string(row[column] == null ? null : String.valueOf(row[column]));
}
out.close(']');
}
out.close(']');
}
out.close('}');
}
/** Each host's address, mask, gateway and DNS server. */