feat(core): modems run — the pair in the project, and a modem of another project hands its frames on (K0–K2)

Measured first: tools/java-oracle's ModemRun joins two networks by a pair
of Java modems over TCP on localhost. The modem has no card and adds no
delay of its own — a frame takes the cables on both sides, nothing more.

The core pairs the two enabled modems on a port (Swift's inProject, with
its conditions and cycle suppression) on Java's timing: no 20 ms. The
modem example of FILIUS now pings through instead of failing the core.
A modem of another project (relay) gives its frames to whoever runs the
engine and puts on its cable what comes back, with this engine's frame
and packet numbers; a frame dies after MAXIMUM_RELAY_HOPS trips.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-11 18:12:27 +00:00
co-authored by Claude Opus 5.5
parent 6f583616f6
commit c85b0e45da
19 changed files with 1743 additions and 44 deletions
+8
View File
@@ -58,6 +58,11 @@ export interface Scenario {
portForwarding?: Record<string, [string, string, string, string][]>;
/** Routers with RIP switched on. */
rip?: string[];
/**
* Modems: Java pairs a server and a client on a port over TCP; the core
* pairs the two modems on a port (the mode is Java's only).
*/
modems?: Record<string, { mode: 'server' | 'client'; port: number }>;
/** Records as `name TYPE target` (Java's hinzuRecord: TTL 3600). */
dnsServers?: Record<string, { records: string[]; recursive?: boolean }>;
steps: {
@@ -124,6 +129,9 @@ export function snapshotOf(scenario: Scenario): TopologySnapshot {
targetNodeId: link.targetNode,
targetPortId: link.targetPort,
})),
remoteLinkConfigurationsByNodeId: new Map(
Object.entries(scenario.modems ?? {}).map(([node, modem]) => [node, { pairIdentifier: `java-modem-port-${modem.port}`, latencyMilliseconds: 20, isEnabled: true }]),
),
deviceConfigurations: new Map(
Object.entries(scenario.devices ?? {}).map(([node, device]) => [
node,