test(java-oracle): TcpRun records TCP as Java FILIUS runs it
Three stories of socket calls on tcp-lan's network (exchange, closedPort, lostData): every frame with TCP flags and numbers, when each call started, returned or failed, and each socket's states. Network building and the packet log move from DhcpRun to ScenarioNetwork. Measured: 3 RTT per attempt (8250 ms at 90 %), an orderly close after a failed send, TIME_WAIT of 3 RTT, the passive side closing by itself on FIN, one SYN only (Java's retry loop ends after the first timeout). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,104 @@
|
|||||||
|
{
|
||||||
|
"frames": {
|
||||||
|
"00000000-0000-0000-0000-000000000101": [
|
||||||
|
{
|
||||||
|
"time": 852,
|
||||||
|
"source": "02:00:00:00:01:13",
|
||||||
|
"destination": "FF:FF:FF:FF:FF:FF",
|
||||||
|
"arp": 1,
|
||||||
|
"senderIp": "192.168.0.30",
|
||||||
|
"targetIp": "192.168.0.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 854,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:13",
|
||||||
|
"arp": 2,
|
||||||
|
"senderIp": "192.168.0.10",
|
||||||
|
"targetIp": "192.168.0.30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1081,
|
||||||
|
"source": "02:00:00:00:01:13",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.30",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 62251,
|
||||||
|
"destinationPort": 81,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "S",
|
||||||
|
"sequence": 1000000,
|
||||||
|
"acknowledgement": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"00000000-0000-0000-0000-000000000102": [
|
||||||
|
{
|
||||||
|
"time": 852,
|
||||||
|
"source": "02:00:00:00:01:13",
|
||||||
|
"destination": "FF:FF:FF:FF:FF:FF",
|
||||||
|
"arp": 1,
|
||||||
|
"senderIp": "192.168.0.30",
|
||||||
|
"targetIp": "192.168.0.10"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"00000000-0000-0000-0000-000000000103": [
|
||||||
|
{
|
||||||
|
"time": 731,
|
||||||
|
"source": "02:00:00:00:01:13",
|
||||||
|
"destination": "FF:FF:FF:FF:FF:FF",
|
||||||
|
"arp": 1,
|
||||||
|
"senderIp": "192.168.0.30",
|
||||||
|
"targetIp": "192.168.0.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 965,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:13",
|
||||||
|
"arp": 2,
|
||||||
|
"senderIp": "192.168.0.10",
|
||||||
|
"targetIp": "192.168.0.30"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 968,
|
||||||
|
"source": "02:00:00:00:01:13",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.30",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 62251,
|
||||||
|
"destinationPort": 81,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "S",
|
||||||
|
"sequence": 1000000,
|
||||||
|
"acknowledgement": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"events": [
|
||||||
|
[
|
||||||
|
715,
|
||||||
|
"client verbinden called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
9020,
|
||||||
|
"client verbinden failed TimeOutException"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"states": {
|
||||||
|
"client": [
|
||||||
|
[
|
||||||
|
714,
|
||||||
|
"CLOSED"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
728,
|
||||||
|
"SYN_SENT"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
8979,
|
||||||
|
"CLOSED"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,574 @@
|
|||||||
|
{
|
||||||
|
"frames": {
|
||||||
|
"00000000-0000-0000-0000-000000000101": [
|
||||||
|
{
|
||||||
|
"time": 857,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "FF:FF:FF:FF:FF:FF",
|
||||||
|
"arp": 1,
|
||||||
|
"senderIp": "192.168.0.20",
|
||||||
|
"targetIp": "192.168.0.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 858,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"arp": 2,
|
||||||
|
"senderIp": "192.168.0.10",
|
||||||
|
"targetIp": "192.168.0.20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1086,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "S",
|
||||||
|
"sequence": 2000000,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1088,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "SA",
|
||||||
|
"sequence": 1000000,
|
||||||
|
"acknowledgement": 2000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1312,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000001,
|
||||||
|
"acknowledgement": 1000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1367,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": "GET /",
|
||||||
|
"tcpFlags": "P",
|
||||||
|
"sequence": 2000001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1368,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 1000001,
|
||||||
|
"acknowledgement": 2000006
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1423,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
"tcpFlags": "",
|
||||||
|
"sequence": 1000001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1646,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000006,
|
||||||
|
"acknowledgement": 1001461
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1647,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
"tcpFlags": "",
|
||||||
|
"sequence": 1001461,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1869,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000006,
|
||||||
|
"acknowledgement": 1002921
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1870,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
"tcpFlags": "P",
|
||||||
|
"sequence": 1002921,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 2092,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000006,
|
||||||
|
"acknowledgement": 1003001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 2148,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "F",
|
||||||
|
"sequence": 2000006,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 2148,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 1003001,
|
||||||
|
"acknowledgement": 2000007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 2204,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "F",
|
||||||
|
"sequence": 1003001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 2426,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000007,
|
||||||
|
"acknowledgement": 1003002
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"00000000-0000-0000-0000-000000000102": [
|
||||||
|
{
|
||||||
|
"time": 733,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "FF:FF:FF:FF:FF:FF",
|
||||||
|
"arp": 1,
|
||||||
|
"senderIp": "192.168.0.20",
|
||||||
|
"targetIp": "192.168.0.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 970,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"arp": 2,
|
||||||
|
"senderIp": "192.168.0.10",
|
||||||
|
"targetIp": "192.168.0.20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 972,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "S",
|
||||||
|
"sequence": 2000000,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1200,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "SA",
|
||||||
|
"sequence": 1000000,
|
||||||
|
"acknowledgement": 2000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1200,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000001,
|
||||||
|
"acknowledgement": 1000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1256,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": "GET /",
|
||||||
|
"tcpFlags": "P",
|
||||||
|
"sequence": 2000001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1479,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 1000001,
|
||||||
|
"acknowledgement": 2000006
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1535,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
"tcpFlags": "",
|
||||||
|
"sequence": 1000001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1535,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000006,
|
||||||
|
"acknowledgement": 1001461
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1758,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
"tcpFlags": "",
|
||||||
|
"sequence": 1001461,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1758,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000006,
|
||||||
|
"acknowledgement": 1002921
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1981,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||||
|
"tcpFlags": "P",
|
||||||
|
"sequence": 1002921,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1981,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000006,
|
||||||
|
"acknowledgement": 1003001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 2037,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "F",
|
||||||
|
"sequence": 2000006,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 2259,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 1003001,
|
||||||
|
"acknowledgement": 2000007
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 2315,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61961,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "F",
|
||||||
|
"sequence": 1003001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 2315,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61961,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000007,
|
||||||
|
"acknowledgement": 1003002
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"00000000-0000-0000-0000-000000000103": [
|
||||||
|
{
|
||||||
|
"time": 857,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "FF:FF:FF:FF:FF:FF",
|
||||||
|
"arp": 1,
|
||||||
|
"senderIp": "192.168.0.20",
|
||||||
|
"targetIp": "192.168.0.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"events": [
|
||||||
|
[
|
||||||
|
216,
|
||||||
|
"server oeffnen called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
717,
|
||||||
|
"client verbinden called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1218,
|
||||||
|
"client verbinden returned"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1218,
|
||||||
|
"client senden called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1319,
|
||||||
|
"server oeffnen returned"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1319,
|
||||||
|
"server empfangen called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1368,
|
||||||
|
"server empfangen returned 5 characters"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1368,
|
||||||
|
"server senden called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1479,
|
||||||
|
"client senden returned"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1479,
|
||||||
|
"client empfangen called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1981,
|
||||||
|
"client empfangen returned 3000 characters"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1981,
|
||||||
|
"client schliessen called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1981,
|
||||||
|
"client schliessen returned"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2092,
|
||||||
|
"server senden returned"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"states": {
|
||||||
|
"client": [
|
||||||
|
[
|
||||||
|
717,
|
||||||
|
"CLOSED"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
729,
|
||||||
|
"SYN_SENT"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1202,
|
||||||
|
"ESTABLISHED"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1982,
|
||||||
|
"FIN_WAIT_1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2260,
|
||||||
|
"FIN_WAIT_2"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2315,
|
||||||
|
"TIME_WAIT"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
10565,
|
||||||
|
"CLOSED"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"server": [
|
||||||
|
[
|
||||||
|
1319,
|
||||||
|
"ESTABLISHED"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2148,
|
||||||
|
"LAST_ACK"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2428,
|
||||||
|
"CLOSED"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,368 @@
|
|||||||
|
{
|
||||||
|
"frames": {
|
||||||
|
"00000000-0000-0000-0000-000000000101": [
|
||||||
|
{
|
||||||
|
"time": 854,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "FF:FF:FF:FF:FF:FF",
|
||||||
|
"arp": 1,
|
||||||
|
"senderIp": "192.168.0.20",
|
||||||
|
"targetIp": "192.168.0.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 855,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"arp": 2,
|
||||||
|
"senderIp": "192.168.0.10",
|
||||||
|
"targetIp": "192.168.0.20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1083,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "S",
|
||||||
|
"sequence": 2000000,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1084,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61897,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "SA",
|
||||||
|
"sequence": 1000000,
|
||||||
|
"acknowledgement": 2000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1307,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000001,
|
||||||
|
"acknowledgement": 1000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 26579,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "F",
|
||||||
|
"sequence": 2000009,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 26579,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61897,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 1000001,
|
||||||
|
"acknowledgement": 2000010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 26635,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61897,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "F",
|
||||||
|
"sequence": 1000001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 26858,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000010,
|
||||||
|
"acknowledgement": 1000002
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"00000000-0000-0000-0000-000000000102": [
|
||||||
|
{
|
||||||
|
"time": 731,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "FF:FF:FF:FF:FF:FF",
|
||||||
|
"arp": 1,
|
||||||
|
"senderIp": "192.168.0.20",
|
||||||
|
"targetIp": "192.168.0.10"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 967,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"arp": 2,
|
||||||
|
"senderIp": "192.168.0.10",
|
||||||
|
"targetIp": "192.168.0.20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 969,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "S",
|
||||||
|
"sequence": 2000000,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1196,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61897,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "SA",
|
||||||
|
"sequence": 1000000,
|
||||||
|
"acknowledgement": 2000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1196,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000001,
|
||||||
|
"acknowledgement": 1000001
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 1717,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": "verloren",
|
||||||
|
"tcpFlags": "P",
|
||||||
|
"sequence": 2000001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 9967,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": "verloren",
|
||||||
|
"tcpFlags": "P",
|
||||||
|
"sequence": 2000001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 18217,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": "verloren",
|
||||||
|
"tcpFlags": "P",
|
||||||
|
"sequence": 2000001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 26467,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "F",
|
||||||
|
"sequence": 2000009,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 26691,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61897,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 1000001,
|
||||||
|
"acknowledgement": 2000010
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 26746,
|
||||||
|
"source": "02:00:00:00:01:11",
|
||||||
|
"destination": "02:00:00:00:01:12",
|
||||||
|
"sourceIp": "192.168.0.10",
|
||||||
|
"destinationIp": "192.168.0.20",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 80,
|
||||||
|
"destinationPort": 61897,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "F",
|
||||||
|
"sequence": 1000001,
|
||||||
|
"acknowledgement": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"time": 26747,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "02:00:00:00:01:11",
|
||||||
|
"sourceIp": "192.168.0.20",
|
||||||
|
"destinationIp": "192.168.0.10",
|
||||||
|
"protocol": 6,
|
||||||
|
"sourcePort": 61897,
|
||||||
|
"destinationPort": 80,
|
||||||
|
"payload": null,
|
||||||
|
"tcpFlags": "A",
|
||||||
|
"sequence": 2000010,
|
||||||
|
"acknowledgement": 1000002
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"00000000-0000-0000-0000-000000000103": [
|
||||||
|
{
|
||||||
|
"time": 854,
|
||||||
|
"source": "02:00:00:00:01:12",
|
||||||
|
"destination": "FF:FF:FF:FF:FF:FF",
|
||||||
|
"arp": 1,
|
||||||
|
"senderIp": "192.168.0.20",
|
||||||
|
"targetIp": "192.168.0.10"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"events": [
|
||||||
|
[
|
||||||
|
215,
|
||||||
|
"server oeffnen called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
715,
|
||||||
|
"client verbinden called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1216,
|
||||||
|
"client verbinden returned"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1317,
|
||||||
|
"server oeffnen returned"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1716,
|
||||||
|
"loss on"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1716,
|
||||||
|
"client senden called"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
26467,
|
||||||
|
"client senden failed TimeOutException"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
26467,
|
||||||
|
"loss off"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"states": {
|
||||||
|
"client": [
|
||||||
|
[
|
||||||
|
715,
|
||||||
|
"CLOSED"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
727,
|
||||||
|
"SYN_SENT"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1197,
|
||||||
|
"ESTABLISHED"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
26469,
|
||||||
|
"FIN_WAIT_1"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
26692,
|
||||||
|
"FIN_WAIT_2"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
26747,
|
||||||
|
"TIME_WAIT"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
34997,
|
||||||
|
"CLOSED"
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"server": [
|
||||||
|
[
|
||||||
|
1317,
|
||||||
|
"ESTABLISHED"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
26580,
|
||||||
|
"LAST_ACK"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
26858,
|
||||||
|
"CLOSED"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -185,3 +185,40 @@ eine Kabellänge später.
|
|||||||
Filius' Mitschnitt selbst ist dabei nicht ganz zuverlässig: Starten zwei
|
Filius' Mitschnitt selbst ist dabei nicht ganz zuverlässig: Starten zwei
|
||||||
Clients zugleich, fehlt auf der Karte des zweiten dessen eigenes DISCOVER
|
Clients zugleich, fehlt auf der Karte des zweiten dessen eigenes DISCOVER
|
||||||
(vier von vier Läufen von `dhcp-lan`; der Server empfängt es).
|
(vier von vier Läufen von `dhcp-lan`; der Server empfängt es).
|
||||||
|
|
||||||
|
## TCP zur Laufzeit
|
||||||
|
|
||||||
|
`TcpRun` spielt auf dem Netz von `tcp-lan` (Server 192.168.0.10, Clients .20
|
||||||
|
und .30) einen festen Ablauf von Socket-Aufrufen ab, wie Filius' Anwendungen
|
||||||
|
sie machen, den Server in einem eigenen Thread. Es schreibt nach
|
||||||
|
`tcp-java-<ablauf>.java.json` die Frames jeder Karte (mit TCP-Flags,
|
||||||
|
Sequenz- und Bestätigungsnummer), wann jeder Aufruf begann, zurückkam oder
|
||||||
|
scheiterte, und jeden Zustand jedes Sockets (alle 2 ms abgefragt). Netzbau
|
||||||
|
und Mitschnitt teilen `DhcpRun` und `TcpRun` in `ScenarioNetwork`.
|
||||||
|
|
||||||
|
* `exchange`: Verbindung zu Port 80, `GET /`, Antwort 3000 × `x` (drei
|
||||||
|
Segmente), der Client schließt, der Server eine Sekunde nach
|
||||||
|
`CLOSE_WAIT`.
|
||||||
|
* `closedPort`: Verbindung zu Port 81, auf dem niemand lauscht.
|
||||||
|
* `lostData`: verbunden, dann gehen alle Frames verloren
|
||||||
|
(`Verbindung.setDrop`, wie der Paketverlust des Kerns), während der Client
|
||||||
|
sendet; der Verlust endet, wenn `senden` scheitert.
|
||||||
|
|
||||||
|
Gemessen (30.09.2026, 90 %, RTT 2750 ms), was Swift anders macht:
|
||||||
|
|
||||||
|
* Jeder Versuch wartet 3 RTT (8250 ms): Daten gehen dreimal hinaus (1720,
|
||||||
|
9970, 18220 ms), `senden` scheitert 8250 ms nach dem dritten.
|
||||||
|
* Scheitert `senden`, schließt Java ordentlich: FIN, ACK, FIN, ACK. Swift
|
||||||
|
setzt den Socket ohne FIN auf CLOSED.
|
||||||
|
* `TIME_WAIT` dauert 3 RTT (8250 ms; oder bis zum nächsten Segment), nicht
|
||||||
|
eine RTT.
|
||||||
|
* Die Gegenseite schließt von selbst: Kommt ein FIN, geht Javas
|
||||||
|
Socket-Thread aus `listen` in `close` und sendet sein FIN sofort
|
||||||
|
(`LAST_ACK` rund 60 ms nach dem FIN), nicht erst, wenn die Anwendung
|
||||||
|
`schliessen` aufruft.
|
||||||
|
* Der Client sendet nur **ein** SYN: Nach dem ersten Zeitablauf setzt
|
||||||
|
`connectClientMode` `closeSocket`, und die Schleife über drei Versuche
|
||||||
|
endet (`verbinden` scheitert nach 3 RTT). Der Server-Socket wiederholt sein
|
||||||
|
SYN+ACK nie.
|
||||||
|
* Startnummern aus einem Zähler über alle TCP-Sockets (1000000, 2000000, …),
|
||||||
|
wie im Kern; der freie Port ist zufällig.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ if [ ! -f "$upstream/target/filius.jar" ]; then
|
|||||||
fi
|
fi
|
||||||
classpath="$upstream/target/filius.jar:$upstream/target/lib/*"
|
classpath="$upstream/target/filius.jar:$upstream/target/lib/*"
|
||||||
mkdir -p "$here/.build"
|
mkdir -p "$here/.build"
|
||||||
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java" "$here/src/DnsHostsCases.java" "$here/src/EmailFileCases.java" "$here/src/BeansDump.java" "$here/src/Base64Cases.java" "$here/src/DhcpRun.java"
|
javac -encoding UTF-8 -d "$here/.build" -cp "$classpath" "$here/src/FlsOracle.java" "$here/src/GetterDefaults.java" "$here/src/IpCheckCases.java" "$here/src/DnsHostsCases.java" "$here/src/EmailFileCases.java" "$here/src/BeansDump.java" "$here/src/Base64Cases.java" "$here/src/ScenarioNetwork.java" "$here/src/DhcpRun.java" "$here/src/TcpRun.java"
|
||||||
# FILIUS writes its settings below $HOME; keep them out of the real one.
|
# FILIUS writes its settings below $HOME; keep them out of the real one.
|
||||||
mkdir -p "$here/.build/home"
|
mkdir -p "$here/.build/home"
|
||||||
# Removed first: a crashed run must not leave the previous result standing.
|
# Removed first: a crashed run must not leave the previous result standing.
|
||||||
@@ -119,3 +119,14 @@ for run in dhcp-lan:8000 dhcp-two-servers:8000 dhcp-conflict:25000 dhcp-no-serve
|
|||||||
"$root/packages/core/test/scenarios/$name.scenario.json" "${run##*:}" "$output" 2>&1 | grep -v 'logback\|^$' || true
|
"$root/packages/core/test/scenarios/$name.scenario.json" "${run##*:}" "$output" 2>&1 | grep -v 'logback\|^$' || true
|
||||||
test -s "$output"
|
test -s "$output"
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# TCP as Java FILIUS runs it: stories of socket calls on tcp-lan's network
|
||||||
|
# (TcpRun); frames, calls and socket states, for the core's TCP comparison.
|
||||||
|
for run in exchange:30000 closedPort:30000 lostData:45000; do
|
||||||
|
story="${run%%:*}"
|
||||||
|
output="$root/packages/core/test/scenarios/tcp-java-$story.java.json"
|
||||||
|
rm -f "$output"
|
||||||
|
HOME="$here/.build/home" xvfb-run -a java -cp "$classpath:$here/.build" TcpRun \
|
||||||
|
"$root/packages/core/test/scenarios/tcp-lan.scenario.json" "$story" "${run##*:}" "$output" 2>&1 | grep -v 'logback\|^$' || true
|
||||||
|
test -s "$output"
|
||||||
|
done
|
||||||
|
|||||||
@@ -1,396 +1,26 @@
|
|||||||
// Runs a core scenario's network in Java FILIUS and records what DHCP really
|
// Runs a core scenario's network in Java FILIUS (ScenarioNetwork) and records
|
||||||
// does: every frame each network card saw (FILIUS' own packet log, the
|
// what DHCP really does: every frame each network card saw and each host's
|
||||||
// Lauscher) and each host's address configuration at the end.
|
// address configuration at the end.
|
||||||
//
|
//
|
||||||
// DhcpRun <scenario.json> <milliseconds> <out.json>
|
// DhcpRun <scenario.json> <milliseconds> <out.json>
|
||||||
//
|
//
|
||||||
// The network is built from the scenario (nodes, links, devices,
|
// The scenario's steps are ignored: the network runs, in real time, for the
|
||||||
// dhcpServers, dhcpClients; steps are ignored) the way the core reads it: a
|
// given milliseconds. Threads make the times vary from run to run; the order
|
||||||
// port's MAC is its `mac`, else the core's stableGeneratedMacAddress. The
|
// of one client's messages does not.
|
||||||
// simulation then runs as the action mode starts it (every system software's
|
|
||||||
// starten()), in real time, for the given milliseconds. Threads make the
|
|
||||||
// times vary from run to run; the order of one client's messages does not.
|
|
||||||
|
|
||||||
import filius.gui.GUIContainer;
|
|
||||||
import filius.hardware.Kabel;
|
|
||||||
import filius.hardware.NetzwerkInterface;
|
|
||||||
import filius.hardware.Port;
|
|
||||||
import filius.hardware.knoten.InternetKnoten;
|
|
||||||
import filius.hardware.knoten.Knoten;
|
|
||||||
import filius.hardware.knoten.LokalerKnoten;
|
|
||||||
import filius.hardware.knoten.Notebook;
|
|
||||||
import filius.hardware.knoten.Rechner;
|
|
||||||
import filius.hardware.knoten.Switch;
|
|
||||||
import filius.rahmenprogramm.nachrichten.Lauscher;
|
|
||||||
import filius.software.dhcp.DHCPServer;
|
|
||||||
import filius.software.netzzugangsschicht.EthernetFrame;
|
|
||||||
import filius.software.system.InternetKnotenBetriebssystem;
|
|
||||||
import filius.software.transportschicht.Segment;
|
|
||||||
import filius.software.vermittlungsschicht.ArpPaket;
|
|
||||||
import filius.software.vermittlungsschicht.IcmpPaket;
|
|
||||||
import filius.software.vermittlungsschicht.IpPaket;
|
|
||||||
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.OutputStreamWriter;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.TreeMap;
|
|
||||||
|
|
||||||
public class DhcpRun {
|
public class DhcpRun {
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
@SuppressWarnings("unchecked")
|
ScenarioNetwork network = ScenarioNetwork.read(args[0]);
|
||||||
Map<String, Object> scenario = (Map<String, Object>) new JsonReader(
|
network.start();
|
||||||
new String(Files.readAllBytes(Paths.get(args[0])), StandardCharsets.UTF_8)).value();
|
Thread.sleep(Long.parseLong(args[1]));
|
||||||
long duration = Long.parseLong(args[1]);
|
ScenarioNetwork.Json out = new ScenarioNetwork.Json();
|
||||||
|
|
||||||
Map<String, Knoten> nodes = new LinkedHashMap<>();
|
|
||||||
Map<String, Port> ports = new HashMap<>();
|
|
||||||
Map<String, String> macByNode = new LinkedHashMap<>();
|
|
||||||
for (Object each : list(scenario.get("nodes"))) {
|
|
||||||
Map<String, Object> node = map(each);
|
|
||||||
String id = (String) node.get("id");
|
|
||||||
String kind = (String) node.get("kind");
|
|
||||||
List<Object> nodePorts = list(node.get("ports"));
|
|
||||||
Knoten knoten;
|
|
||||||
switch (kind) {
|
|
||||||
case "pc":
|
|
||||||
knoten = new Rechner();
|
|
||||||
break;
|
|
||||||
case "notebook":
|
|
||||||
knoten = new Notebook();
|
|
||||||
break;
|
|
||||||
case "networkSwitch":
|
|
||||||
knoten = new Switch();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException("node kind " + kind + " is not built by this tool");
|
|
||||||
}
|
|
||||||
knoten.setName(id);
|
|
||||||
if (knoten instanceof InternetKnoten) {
|
|
||||||
if (nodePorts.size() != 1) throw new IllegalArgumentException("a host has one port here");
|
|
||||||
Map<String, Object> port = map(nodePorts.get(0));
|
|
||||||
NetzwerkInterface nic = ((InternetKnoten) knoten).getNetzwerkInterfaces().get(0);
|
|
||||||
String mac = port.containsKey("mac") ? (String) port.get("mac") : stableMac((String) port.get("id"));
|
|
||||||
nic.setMac(mac);
|
|
||||||
ports.put((String) port.get("id"), nic.getPort());
|
|
||||||
macByNode.put(id, mac);
|
|
||||||
} else {
|
|
||||||
LinkedList<Port> switchPorts = ((LokalerKnoten) knoten).getAnschluesse();
|
|
||||||
for (int index = 0; index < nodePorts.size(); index++) {
|
|
||||||
ports.put((String) map(nodePorts.get(index)).get("id"), switchPorts.get(index));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nodes.put(id, knoten);
|
|
||||||
}
|
|
||||||
for (Map.Entry<String, Object> entry : map(scenario.getOrDefault("devices", new HashMap<>())).entrySet()) {
|
|
||||||
Map<String, Object> device = map(entry.getValue());
|
|
||||||
NetzwerkInterface nic = ((InternetKnoten) nodes.get(entry.getKey())).getNetzwerkInterfaces().get(0);
|
|
||||||
nic.setIp((String) device.get("ip"));
|
|
||||||
nic.setSubnetzMaske((String) device.get("mask"));
|
|
||||||
nic.setGateway((String) device.getOrDefault("gateway", ""));
|
|
||||||
nic.setDns((String) device.getOrDefault("dns", ""));
|
|
||||||
}
|
|
||||||
for (Object each : list(scenario.get("links"))) {
|
|
||||||
Map<String, Object> link = map(each);
|
|
||||||
Kabel cable = new Kabel();
|
|
||||||
cable.setAnschluesse(new Port[] { ports.get(link.get("sourcePort")), ports.get(link.get("targetPort")) });
|
|
||||||
}
|
|
||||||
List<String> servers = new ArrayList<>();
|
|
||||||
for (Map.Entry<String, Object> entry : map(scenario.getOrDefault("dhcpServers", new HashMap<>())).entrySet()) {
|
|
||||||
Map<String, Object> config = map(entry.getValue());
|
|
||||||
DHCPServer server = system(nodes.get(entry.getKey())).getDHCPServer();
|
|
||||||
server.setUntergrenze((String) config.getOrDefault("lower", "0.0.0.0"));
|
|
||||||
server.setObergrenze((String) config.getOrDefault("upper", "0.0.0.0"));
|
|
||||||
server.setGatewayip((String) config.getOrDefault("gateway", "0.0.0.0"));
|
|
||||||
server.setDnsserverip((String) config.getOrDefault("dns", "0.0.0.0"));
|
|
||||||
server.setOwnSettings(Boolean.TRUE.equals(config.get("own")));
|
|
||||||
for (Object assignment : list(config.getOrDefault("staticAssignments", new ArrayList<>()))) {
|
|
||||||
server.addStaticAssignment((String) list(assignment).get(0), (String) list(assignment).get(1));
|
|
||||||
}
|
|
||||||
server.setAktiv(Boolean.TRUE.equals(config.get("active")));
|
|
||||||
servers.add(entry.getKey());
|
|
||||||
}
|
|
||||||
for (Object each : list(scenario.getOrDefault("dhcpClients", new ArrayList<>()))) {
|
|
||||||
system(nodes.get((String) each)).setDHCPKonfiguration(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Switches and DHCP servers first: FILIUS' client waits for every active
|
|
||||||
// server to have started (waitUntilDhcpServerStarted, through the GUI's
|
|
||||||
// node list, which this tool has not got).
|
|
||||||
// FILIUS' window exists before a simulation starts; created lazily and
|
|
||||||
// unsynchronized, the first clients to ask for it would race.
|
|
||||||
GUIContainer.getGUIContainer();
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
for (Map.Entry<String, Knoten> entry : nodes.entrySet()) {
|
|
||||||
if (entry.getValue() instanceof Switch || servers.contains(entry.getKey())) entry.getValue().getSystemSoftware().starten();
|
|
||||||
}
|
|
||||||
Thread.sleep(200);
|
|
||||||
for (Map.Entry<String, Knoten> entry : nodes.entrySet()) {
|
|
||||||
if (!(entry.getValue() instanceof Switch || servers.contains(entry.getKey()))) entry.getValue().getSystemSoftware().starten();
|
|
||||||
}
|
|
||||||
Thread.sleep(duration);
|
|
||||||
|
|
||||||
Field field = Lauscher.class.getDeclaredField("datenEinheiten");
|
|
||||||
field.setAccessible(true);
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Map<String, LinkedList<Object[]>> log = (Map<String, LinkedList<Object[]>>) field.get(Lauscher.getLauscher());
|
|
||||||
|
|
||||||
Json out = new Json();
|
|
||||||
out.open('{');
|
out.open('{');
|
||||||
out.key("frames").open('{');
|
network.writeFrames(out);
|
||||||
for (Map.Entry<String, String> entry : macByNode.entrySet()) {
|
network.writeDevices(out);
|
||||||
out.key(entry.getKey()).open('[');
|
|
||||||
LinkedList<Object[]> frames = log.get(entry.getValue());
|
|
||||||
if (frames != null) {
|
|
||||||
synchronized (frames) {
|
|
||||||
for (Object[] stamped : frames) frame(out, ((Long) stamped[0]) - start, (EthernetFrame) stamped[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out.close(']');
|
|
||||||
}
|
|
||||||
out.close('}');
|
out.close('}');
|
||||||
out.key("devices").open('{');
|
network.stop();
|
||||||
for (Map.Entry<String, Knoten> entry : nodes.entrySet()) {
|
ScenarioNetwork.write(args[2], out);
|
||||||
if (!(entry.getValue() instanceof InternetKnoten)) continue;
|
|
||||||
NetzwerkInterface nic = ((InternetKnoten) entry.getValue()).getNetzwerkInterfaces().get(0);
|
|
||||||
out.key(entry.getKey()).open('[').string(nic.getIp()).string(nic.getSubnetzMaske()).string(nic.getGateway())
|
|
||||||
.string(nic.getDns()).close(']');
|
|
||||||
}
|
|
||||||
out.close('}');
|
|
||||||
out.close('}');
|
|
||||||
|
|
||||||
for (Knoten knoten : nodes.values()) {
|
|
||||||
try {
|
|
||||||
knoten.getSystemSoftware().beenden();
|
|
||||||
} catch (Exception e) {}
|
|
||||||
}
|
|
||||||
try (Writer writer = new OutputStreamWriter(new FileOutputStream(args[2]), StandardCharsets.UTF_8)) {
|
|
||||||
writer.write(out.toString());
|
|
||||||
writer.write('\n');
|
|
||||||
}
|
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void frame(Json out, long time, EthernetFrame frame) {
|
|
||||||
out.open('{').key("time").number(time).key("source").string(frame.getQuellMacAdresse()).key("destination")
|
|
||||||
.string(frame.getZielMacAdresse());
|
|
||||||
Object data = frame.getDaten();
|
|
||||||
if (data instanceof ArpPaket) {
|
|
||||||
ArpPaket arp = (ArpPaket) data;
|
|
||||||
out.key("arp").number(arp.getOperation()).key("senderIp").string(arp.getSenderIP()).key("targetIp")
|
|
||||||
.string(arp.getTargetIP());
|
|
||||||
} else if (data instanceof IcmpPaket) {
|
|
||||||
out.key("icmp").number(((IcmpPaket) data).getIcmpType());
|
|
||||||
} else if (data instanceof IpPaket) {
|
|
||||||
IpPaket ip = (IpPaket) data;
|
|
||||||
Segment segment = ip.getSegment();
|
|
||||||
out.key("sourceIp").string(ip.getSender()).key("destinationIp").string(ip.getEmpfaenger()).key("protocol")
|
|
||||||
.number(ip.getProtocol()).key("sourcePort").number(segment.getQuellPort()).key("destinationPort")
|
|
||||||
.number(segment.getZielPort()).key("payload").string(segment.getDaten());
|
|
||||||
}
|
|
||||||
out.close('}');
|
|
||||||
}
|
|
||||||
|
|
||||||
private static InternetKnotenBetriebssystem system(Knoten knoten) {
|
|
||||||
return (InternetKnotenBetriebssystem) knoten.getSystemSoftware();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The core's stableGeneratedMacAddress (packages/core/src/model/node.ts). */
|
|
||||||
static String stableMac(String portId) {
|
|
||||||
String compact = portId.toUpperCase().replace("-", "");
|
|
||||||
String suffix = compact.substring(compact.length() - 10);
|
|
||||||
StringBuilder mac = new StringBuilder("02");
|
|
||||||
for (int offset = 0; offset < suffix.length(); offset += 2) mac.append(':').append(suffix, offset, offset + 2);
|
|
||||||
return mac.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static Map<String, Object> map(Object value) {
|
|
||||||
return (Map<String, Object>) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private static List<Object> list(Object value) {
|
|
||||||
return (List<Object>) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Just enough JSON for a scenario: objects, arrays, strings, numbers, booleans, null. */
|
|
||||||
static final class JsonReader {
|
|
||||||
private final String text;
|
|
||||||
private int position;
|
|
||||||
|
|
||||||
JsonReader(String text) {
|
|
||||||
this.text = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object value() {
|
|
||||||
skip();
|
|
||||||
char c = text.charAt(position);
|
|
||||||
if (c == '{') {
|
|
||||||
Map<String, Object> result = new TreeMap<>();
|
|
||||||
position++;
|
|
||||||
skip();
|
|
||||||
if (text.charAt(position) == '}') {
|
|
||||||
position++;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
for (;;) {
|
|
||||||
skip();
|
|
||||||
String key = (String) value();
|
|
||||||
skip();
|
|
||||||
expect(':');
|
|
||||||
result.put(key, value());
|
|
||||||
skip();
|
|
||||||
if (text.charAt(position++) == '}') return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (c == '[') {
|
|
||||||
List<Object> result = new ArrayList<>();
|
|
||||||
position++;
|
|
||||||
skip();
|
|
||||||
if (text.charAt(position) == ']') {
|
|
||||||
position++;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
for (;;) {
|
|
||||||
result.add(value());
|
|
||||||
skip();
|
|
||||||
if (text.charAt(position++) == ']') return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (c == '"') {
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
position++;
|
|
||||||
for (char each = text.charAt(position++); each != '"'; each = text.charAt(position++)) {
|
|
||||||
if (each == '\\') {
|
|
||||||
char escaped = text.charAt(position++);
|
|
||||||
switch (escaped) {
|
|
||||||
case 'n':
|
|
||||||
result.append('\n');
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
result.append('\t');
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
result.append((char) Integer.parseInt(text.substring(position, position + 4), 16));
|
|
||||||
position += 4;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
result.append(escaped);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
result.append(each);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
if (text.startsWith("true", position)) {
|
|
||||||
position += 4;
|
|
||||||
return Boolean.TRUE;
|
|
||||||
}
|
|
||||||
if (text.startsWith("false", position)) {
|
|
||||||
position += 5;
|
|
||||||
return Boolean.FALSE;
|
|
||||||
}
|
|
||||||
if (text.startsWith("null", position)) {
|
|
||||||
position += 4;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
int begin = position;
|
|
||||||
while (position < text.length() && "+-.eE0123456789".indexOf(text.charAt(position)) >= 0) position++;
|
|
||||||
return Double.parseDouble(text.substring(begin, position));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void skip() {
|
|
||||||
while (position < text.length() && Character.isWhitespace(text.charAt(position))) position++;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void expect(char c) {
|
|
||||||
if (text.charAt(position++) != c) throw new IllegalArgumentException("expected " + c + " at " + (position - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** A JSON writer with commas and indentation. */
|
|
||||||
static final class Json {
|
|
||||||
private final StringBuilder text = new StringBuilder();
|
|
||||||
private final LinkedList<Boolean> first = new LinkedList<>();
|
|
||||||
private boolean afterKey;
|
|
||||||
|
|
||||||
private void separate() {
|
|
||||||
if (afterKey) {
|
|
||||||
afterKey = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (first.isEmpty()) return;
|
|
||||||
if (!first.peek()) text.append(',');
|
|
||||||
first.pop();
|
|
||||||
first.push(false);
|
|
||||||
text.append('\n');
|
|
||||||
for (int i = 0; i < first.size(); i++) text.append(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
Json open(char bracket) {
|
|
||||||
separate();
|
|
||||||
text.append(bracket);
|
|
||||||
first.push(true);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Json close(char bracket) {
|
|
||||||
boolean empty = first.pop();
|
|
||||||
if (!empty) {
|
|
||||||
text.append('\n');
|
|
||||||
for (int i = 0; i < first.size(); i++) text.append(" ");
|
|
||||||
}
|
|
||||||
text.append(bracket);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Json key(String key) {
|
|
||||||
separate();
|
|
||||||
quote(key);
|
|
||||||
text.append(": ");
|
|
||||||
afterKey = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Json string(String value) {
|
|
||||||
separate();
|
|
||||||
if (value == null) text.append("null");
|
|
||||||
else quote(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
Json number(long value) {
|
|
||||||
separate();
|
|
||||||
text.append(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void quote(String value) {
|
|
||||||
text.append('"');
|
|
||||||
for (char c : value.toCharArray()) {
|
|
||||||
if (c == '"' || c == '\\') text.append('\\').append(c);
|
|
||||||
else if (c == '\n') text.append("\\n");
|
|
||||||
else if (c < 0x20) text.append(String.format("\\u%04x", (int) c));
|
|
||||||
else text.append(c);
|
|
||||||
}
|
|
||||||
text.append('"');
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return text.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,418 @@
|
|||||||
|
// A core scenario's network (packages/core/test/scenarios/*.scenario.json:
|
||||||
|
// nodes, links, devices, dhcpServers, dhcpClients) built in Java FILIUS the
|
||||||
|
// way the core reads it: a port's MAC is its `mac`, else the core's
|
||||||
|
// stableGeneratedMacAddress. Started as the action mode starts it (every
|
||||||
|
// system software's starten()); afterwards every frame each network card saw
|
||||||
|
// (FILIUS' own packet log, the Lauscher) and each host's addresses. Shared by
|
||||||
|
// DhcpRun and TcpRun.
|
||||||
|
|
||||||
|
import filius.gui.GUIContainer;
|
||||||
|
import filius.hardware.Kabel;
|
||||||
|
import filius.hardware.NetzwerkInterface;
|
||||||
|
import filius.hardware.Port;
|
||||||
|
import filius.hardware.knoten.InternetKnoten;
|
||||||
|
import filius.hardware.knoten.Knoten;
|
||||||
|
import filius.hardware.knoten.LokalerKnoten;
|
||||||
|
import filius.hardware.knoten.Notebook;
|
||||||
|
import filius.hardware.knoten.Rechner;
|
||||||
|
import filius.hardware.knoten.Switch;
|
||||||
|
import filius.rahmenprogramm.nachrichten.Lauscher;
|
||||||
|
import filius.software.dhcp.DHCPServer;
|
||||||
|
import filius.software.netzzugangsschicht.EthernetFrame;
|
||||||
|
import filius.software.system.InternetKnotenBetriebssystem;
|
||||||
|
import filius.software.transportschicht.Segment;
|
||||||
|
import filius.software.transportschicht.TcpSegment;
|
||||||
|
import filius.software.vermittlungsschicht.ArpPaket;
|
||||||
|
import filius.software.vermittlungsschicht.IcmpPaket;
|
||||||
|
import filius.software.vermittlungsschicht.IpPaket;
|
||||||
|
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
public class ScenarioNetwork {
|
||||||
|
final Map<String, Knoten> nodes = new LinkedHashMap<>();
|
||||||
|
final Map<String, String> macByNode = new LinkedHashMap<>();
|
||||||
|
final List<String> servers = new ArrayList<>();
|
||||||
|
long start;
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
static ScenarioNetwork read(String path) throws Exception {
|
||||||
|
Map<String, Object> scenario = (Map<String, Object>) new JsonReader(
|
||||||
|
new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8)).value();
|
||||||
|
ScenarioNetwork network = new ScenarioNetwork();
|
||||||
|
network.build(scenario);
|
||||||
|
return network;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void build(Map<String, Object> scenario) {
|
||||||
|
Map<String, Port> ports = new HashMap<>();
|
||||||
|
for (Object each : list(scenario.get("nodes"))) {
|
||||||
|
Map<String, Object> node = map(each);
|
||||||
|
String id = (String) node.get("id");
|
||||||
|
String kind = (String) node.get("kind");
|
||||||
|
List<Object> nodePorts = list(node.get("ports"));
|
||||||
|
Knoten knoten;
|
||||||
|
switch (kind) {
|
||||||
|
case "pc":
|
||||||
|
knoten = new Rechner();
|
||||||
|
break;
|
||||||
|
case "notebook":
|
||||||
|
knoten = new Notebook();
|
||||||
|
break;
|
||||||
|
case "networkSwitch":
|
||||||
|
knoten = new Switch();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("node kind " + kind + " is not built by this tool");
|
||||||
|
}
|
||||||
|
knoten.setName(id);
|
||||||
|
if (knoten instanceof InternetKnoten) {
|
||||||
|
if (nodePorts.size() != 1) throw new IllegalArgumentException("a host has one port here");
|
||||||
|
Map<String, Object> port = map(nodePorts.get(0));
|
||||||
|
NetzwerkInterface nic = ((InternetKnoten) knoten).getNetzwerkInterfaces().get(0);
|
||||||
|
String mac = port.containsKey("mac") ? (String) port.get("mac") : stableMac((String) port.get("id"));
|
||||||
|
nic.setMac(mac);
|
||||||
|
ports.put((String) port.get("id"), nic.getPort());
|
||||||
|
macByNode.put(id, mac);
|
||||||
|
} else {
|
||||||
|
LinkedList<Port> switchPorts = ((LokalerKnoten) knoten).getAnschluesse();
|
||||||
|
for (int index = 0; index < nodePorts.size(); index++) {
|
||||||
|
ports.put((String) map(nodePorts.get(index)).get("id"), switchPorts.get(index));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodes.put(id, knoten);
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Object> entry : map(scenario.getOrDefault("devices", new HashMap<>())).entrySet()) {
|
||||||
|
Map<String, Object> device = map(entry.getValue());
|
||||||
|
NetzwerkInterface nic = ((InternetKnoten) nodes.get(entry.getKey())).getNetzwerkInterfaces().get(0);
|
||||||
|
nic.setIp((String) device.get("ip"));
|
||||||
|
nic.setSubnetzMaske((String) device.get("mask"));
|
||||||
|
nic.setGateway((String) device.getOrDefault("gateway", ""));
|
||||||
|
nic.setDns((String) device.getOrDefault("dns", ""));
|
||||||
|
}
|
||||||
|
for (Object each : list(scenario.get("links"))) {
|
||||||
|
Map<String, Object> link = map(each);
|
||||||
|
Kabel cable = new Kabel();
|
||||||
|
cable.setAnschluesse(new Port[] { ports.get(link.get("sourcePort")), ports.get(link.get("targetPort")) });
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Object> entry : map(scenario.getOrDefault("dhcpServers", new HashMap<>())).entrySet()) {
|
||||||
|
Map<String, Object> config = map(entry.getValue());
|
||||||
|
DHCPServer server = system(nodes.get(entry.getKey())).getDHCPServer();
|
||||||
|
server.setUntergrenze((String) config.getOrDefault("lower", "0.0.0.0"));
|
||||||
|
server.setObergrenze((String) config.getOrDefault("upper", "0.0.0.0"));
|
||||||
|
server.setGatewayip((String) config.getOrDefault("gateway", "0.0.0.0"));
|
||||||
|
server.setDnsserverip((String) config.getOrDefault("dns", "0.0.0.0"));
|
||||||
|
server.setOwnSettings(Boolean.TRUE.equals(config.get("own")));
|
||||||
|
for (Object assignment : list(config.getOrDefault("staticAssignments", new ArrayList<>()))) {
|
||||||
|
server.addStaticAssignment((String) list(assignment).get(0), (String) list(assignment).get(1));
|
||||||
|
}
|
||||||
|
server.setAktiv(Boolean.TRUE.equals(config.get("active")));
|
||||||
|
servers.add(entry.getKey());
|
||||||
|
}
|
||||||
|
for (Object each : list(scenario.getOrDefault("dhcpClients", new ArrayList<>()))) {
|
||||||
|
system(nodes.get((String) each)).setDHCPKonfiguration(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Starts the simulation; times in the log count from here. */
|
||||||
|
void start() throws InterruptedException {
|
||||||
|
// Switches and DHCP servers first: FILIUS' client waits for every active
|
||||||
|
// server to have started (waitUntilDhcpServerStarted, through the GUI's
|
||||||
|
// node list, which this tool has not got).
|
||||||
|
// FILIUS' window exists before a simulation starts; created lazily and
|
||||||
|
// unsynchronized, the first clients to ask for it would race.
|
||||||
|
GUIContainer.getGUIContainer();
|
||||||
|
start = System.currentTimeMillis();
|
||||||
|
for (Map.Entry<String, Knoten> entry : nodes.entrySet()) {
|
||||||
|
if (entry.getValue() instanceof Switch || servers.contains(entry.getKey())) entry.getValue().getSystemSoftware().starten();
|
||||||
|
}
|
||||||
|
Thread.sleep(200);
|
||||||
|
for (Map.Entry<String, Knoten> entry : nodes.entrySet()) {
|
||||||
|
if (!(entry.getValue() instanceof Switch || servers.contains(entry.getKey()))) entry.getValue().getSystemSoftware().starten();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
InternetKnotenBetriebssystem system(String nodeId) {
|
||||||
|
return (InternetKnotenBetriebssystem) nodes.get(nodeId).getSystemSoftware();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Every frame each host's card saw, by node. */
|
||||||
|
void writeFrames(Json out) throws Exception {
|
||||||
|
Field field = Lauscher.class.getDeclaredField("datenEinheiten");
|
||||||
|
field.setAccessible(true);
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
Map<String, LinkedList<Object[]>> log = (Map<String, LinkedList<Object[]>>) field.get(Lauscher.getLauscher());
|
||||||
|
out.key("frames").open('{');
|
||||||
|
for (Map.Entry<String, String> entry : macByNode.entrySet()) {
|
||||||
|
out.key(entry.getKey()).open('[');
|
||||||
|
LinkedList<Object[]> frames = log.get(entry.getValue());
|
||||||
|
if (frames != null) {
|
||||||
|
synchronized (frames) {
|
||||||
|
for (Object[] stamped : frames) frame(out, ((Long) stamped[0]) - start, (EthernetFrame) stamped[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.close(']');
|
||||||
|
}
|
||||||
|
out.close('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Each host's address, mask, gateway and DNS server. */
|
||||||
|
void writeDevices(Json out) {
|
||||||
|
out.key("devices").open('{');
|
||||||
|
for (Map.Entry<String, Knoten> entry : nodes.entrySet()) {
|
||||||
|
if (!(entry.getValue() instanceof InternetKnoten)) continue;
|
||||||
|
NetzwerkInterface nic = ((InternetKnoten) entry.getValue()).getNetzwerkInterfaces().get(0);
|
||||||
|
out.key(entry.getKey()).open('[').string(nic.getIp()).string(nic.getSubnetzMaske()).string(nic.getGateway())
|
||||||
|
.string(nic.getDns()).close(']');
|
||||||
|
}
|
||||||
|
out.close('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
void stop() {
|
||||||
|
for (Knoten knoten : nodes.values()) {
|
||||||
|
try {
|
||||||
|
knoten.getSystemSoftware().beenden();
|
||||||
|
} catch (Exception e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write(String path, Json out) throws Exception {
|
||||||
|
try (Writer writer = new OutputStreamWriter(new FileOutputStream(path), StandardCharsets.UTF_8)) {
|
||||||
|
writer.write(out.toString());
|
||||||
|
writer.write('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void frame(Json out, long time, EthernetFrame frame) {
|
||||||
|
out.open('{').key("time").number(time).key("source").string(frame.getQuellMacAdresse()).key("destination")
|
||||||
|
.string(frame.getZielMacAdresse());
|
||||||
|
Object data = frame.getDaten();
|
||||||
|
if (data instanceof ArpPaket) {
|
||||||
|
ArpPaket arp = (ArpPaket) data;
|
||||||
|
out.key("arp").number(arp.getOperation()).key("senderIp").string(arp.getSenderIP()).key("targetIp")
|
||||||
|
.string(arp.getTargetIP());
|
||||||
|
} else if (data instanceof IcmpPaket) {
|
||||||
|
out.key("icmp").number(((IcmpPaket) data).getIcmpType());
|
||||||
|
} else if (data instanceof IpPaket) {
|
||||||
|
IpPaket ip = (IpPaket) data;
|
||||||
|
Segment segment = ip.getSegment();
|
||||||
|
out.key("sourceIp").string(ip.getSender()).key("destinationIp").string(ip.getEmpfaenger()).key("protocol")
|
||||||
|
.number(ip.getProtocol()).key("sourcePort").number(segment.getQuellPort()).key("destinationPort")
|
||||||
|
.number(segment.getZielPort()).key("payload").string(segment.getDaten());
|
||||||
|
if (segment instanceof TcpSegment) {
|
||||||
|
TcpSegment tcp = (TcpSegment) segment;
|
||||||
|
String flags = (tcp.isSyn() ? "S" : "") + (tcp.isAck() ? "A" : "") + (tcp.isFin() ? "F" : "")
|
||||||
|
+ (tcp.isPush() ? "P" : "") + (tcp.isRst() ? "R" : "");
|
||||||
|
out.key("tcpFlags").string(flags).key("sequence").number(tcp.getSeqNummer()).key("acknowledgement")
|
||||||
|
.number(tcp.getAckNummer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out.close('}');
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InternetKnotenBetriebssystem system(Knoten knoten) {
|
||||||
|
return (InternetKnotenBetriebssystem) knoten.getSystemSoftware();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The core's stableGeneratedMacAddress (packages/core/src/model/node.ts). */
|
||||||
|
static String stableMac(String portId) {
|
||||||
|
String compact = portId.toUpperCase().replace("-", "");
|
||||||
|
String suffix = compact.substring(compact.length() - 10);
|
||||||
|
StringBuilder mac = new StringBuilder("02");
|
||||||
|
for (int offset = 0; offset < suffix.length(); offset += 2) mac.append(':').append(suffix, offset, offset + 2);
|
||||||
|
return mac.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static Map<String, Object> map(Object value) {
|
||||||
|
return (Map<String, Object>) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private static List<Object> list(Object value) {
|
||||||
|
return (List<Object>) value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Just enough JSON for a scenario: objects, arrays, strings, numbers, booleans, null. */
|
||||||
|
static final class JsonReader {
|
||||||
|
private final String text;
|
||||||
|
private int position;
|
||||||
|
|
||||||
|
JsonReader(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object value() {
|
||||||
|
skip();
|
||||||
|
char c = text.charAt(position);
|
||||||
|
if (c == '{') {
|
||||||
|
Map<String, Object> result = new TreeMap<>();
|
||||||
|
position++;
|
||||||
|
skip();
|
||||||
|
if (text.charAt(position) == '}') {
|
||||||
|
position++;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
skip();
|
||||||
|
String key = (String) value();
|
||||||
|
skip();
|
||||||
|
expect(':');
|
||||||
|
result.put(key, value());
|
||||||
|
skip();
|
||||||
|
if (text.charAt(position++) == '}') return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c == '[') {
|
||||||
|
List<Object> result = new ArrayList<>();
|
||||||
|
position++;
|
||||||
|
skip();
|
||||||
|
if (text.charAt(position) == ']') {
|
||||||
|
position++;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (;;) {
|
||||||
|
result.add(value());
|
||||||
|
skip();
|
||||||
|
if (text.charAt(position++) == ']') return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (c == '"') {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
position++;
|
||||||
|
for (char each = text.charAt(position++); each != '"'; each = text.charAt(position++)) {
|
||||||
|
if (each == '\\') {
|
||||||
|
char escaped = text.charAt(position++);
|
||||||
|
switch (escaped) {
|
||||||
|
case 'n':
|
||||||
|
result.append('\n');
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
result.append('\t');
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
result.append((char) Integer.parseInt(text.substring(position, position + 4), 16));
|
||||||
|
position += 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result.append(escaped);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.append(each);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
if (text.startsWith("true", position)) {
|
||||||
|
position += 4;
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
if (text.startsWith("false", position)) {
|
||||||
|
position += 5;
|
||||||
|
return Boolean.FALSE;
|
||||||
|
}
|
||||||
|
if (text.startsWith("null", position)) {
|
||||||
|
position += 4;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
int begin = position;
|
||||||
|
while (position < text.length() && "+-.eE0123456789".indexOf(text.charAt(position)) >= 0) position++;
|
||||||
|
return Double.parseDouble(text.substring(begin, position));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void skip() {
|
||||||
|
while (position < text.length() && Character.isWhitespace(text.charAt(position))) position++;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void expect(char c) {
|
||||||
|
if (text.charAt(position++) != c) throw new IllegalArgumentException("expected " + c + " at " + (position - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A JSON writer with commas and indentation. */
|
||||||
|
static final class Json {
|
||||||
|
private final StringBuilder text = new StringBuilder();
|
||||||
|
private final LinkedList<Boolean> first = new LinkedList<>();
|
||||||
|
private boolean afterKey;
|
||||||
|
|
||||||
|
private void separate() {
|
||||||
|
if (afterKey) {
|
||||||
|
afterKey = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (first.isEmpty()) return;
|
||||||
|
if (!first.peek()) text.append(',');
|
||||||
|
first.pop();
|
||||||
|
first.push(false);
|
||||||
|
text.append('\n');
|
||||||
|
for (int i = 0; i < first.size(); i++) text.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
Json open(char bracket) {
|
||||||
|
separate();
|
||||||
|
text.append(bracket);
|
||||||
|
first.push(true);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json close(char bracket) {
|
||||||
|
boolean empty = first.pop();
|
||||||
|
if (!empty) {
|
||||||
|
text.append('\n');
|
||||||
|
for (int i = 0; i < first.size(); i++) text.append(" ");
|
||||||
|
}
|
||||||
|
text.append(bracket);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json key(String key) {
|
||||||
|
separate();
|
||||||
|
quote(key);
|
||||||
|
text.append(": ");
|
||||||
|
afterKey = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json string(String value) {
|
||||||
|
separate();
|
||||||
|
if (value == null) text.append("null");
|
||||||
|
else quote(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Json number(long value) {
|
||||||
|
separate();
|
||||||
|
text.append(value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void quote(String value) {
|
||||||
|
text.append('"');
|
||||||
|
for (char c : value.toCharArray()) {
|
||||||
|
if (c == '"' || c == '\\') text.append('\\').append(c);
|
||||||
|
else if (c == '\n') text.append("\\n");
|
||||||
|
else if (c < 0x20) text.append(String.format("\\u%04x", (int) c));
|
||||||
|
else text.append(c);
|
||||||
|
}
|
||||||
|
text.append('"');
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return text.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
// Runs a story of TCP calls on a core scenario's network in Java FILIUS
|
||||||
|
// (ScenarioNetwork) and records what really happens: every frame each card
|
||||||
|
// saw, when each call started, returned or failed, and every state each
|
||||||
|
// socket went through (polled every few milliseconds).
|
||||||
|
//
|
||||||
|
// TcpRun <scenario.json> <story> <milliseconds> <out.json>
|
||||||
|
//
|
||||||
|
// The stories use the network of tcp-lan (server 192.168.0.10, clients
|
||||||
|
// 192.168.0.20 and .30) and run the calls as FILIUS' applications do, the
|
||||||
|
// server's in a thread of its own:
|
||||||
|
// exchange the client connects to port 80, sends "GET /", the server
|
||||||
|
// answers with 3000 x (three segments); the client closes,
|
||||||
|
// the server closes a second after it saw CLOSE_WAIT
|
||||||
|
// closedPort a client connects to port 81, where nothing listens
|
||||||
|
// lostData connected, all frames are lost (Verbindung.setDrop) while
|
||||||
|
// the client sends; loss ends when senden fails
|
||||||
|
|
||||||
|
import filius.hardware.Verbindung;
|
||||||
|
import filius.software.transportschicht.ServerSocket;
|
||||||
|
import filius.software.transportschicht.Socket;
|
||||||
|
import filius.software.transportschicht.TCPSocket;
|
||||||
|
import filius.software.vermittlungsschicht.IpPaket;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TcpRun {
|
||||||
|
static final String SERVER = "00000000-0000-0000-0000-000000000101";
|
||||||
|
static final String CLIENT = "00000000-0000-0000-0000-000000000102";
|
||||||
|
static final String OTHER_CLIENT = "00000000-0000-0000-0000-000000000103";
|
||||||
|
|
||||||
|
static ScenarioNetwork network;
|
||||||
|
static final List<Object[]> events = new ArrayList<>();
|
||||||
|
static final Map<String, List<Object[]>> states = new LinkedHashMap<>();
|
||||||
|
static final Map<String, TCPSocket> watched = new LinkedHashMap<>();
|
||||||
|
|
||||||
|
static synchronized void event(String what) {
|
||||||
|
events.add(new Object[] { System.currentTimeMillis() - network.start, what });
|
||||||
|
}
|
||||||
|
|
||||||
|
static synchronized void watch(String label, Socket socket) {
|
||||||
|
watched.put(label, (TCPSocket) socket);
|
||||||
|
states.put(label, new ArrayList<>());
|
||||||
|
poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
static synchronized void poll() {
|
||||||
|
for (Map.Entry<String, TCPSocket> entry : watched.entrySet()) {
|
||||||
|
List<Object[]> seen = states.get(entry.getKey());
|
||||||
|
String state = entry.getValue().getStateAsString();
|
||||||
|
if (seen.isEmpty() || !seen.get(seen.size() - 1)[1].equals(state)) {
|
||||||
|
seen.add(new Object[] { System.currentTimeMillis() - network.start, state });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Call {
|
||||||
|
Object run() throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A call with its start and its end (result or exception) in the events. */
|
||||||
|
static Object call(String label, Call call) {
|
||||||
|
event(label + " called");
|
||||||
|
try {
|
||||||
|
Object result = call.run();
|
||||||
|
event(label + " returned" + (result instanceof String ? " " + ((String) result).length() + " characters" : ""));
|
||||||
|
return result;
|
||||||
|
} catch (Exception e) {
|
||||||
|
event(label + " failed " + e.getClass().getSimpleName());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static Thread server(Call body) {
|
||||||
|
Thread thread = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
body.run();
|
||||||
|
} catch (Exception e) {
|
||||||
|
event("server failed " + e.getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.start();
|
||||||
|
return thread;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String repeat(String text, int count) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
for (int i = 0; i < count; i++) result.append(text);
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
network = ScenarioNetwork.read(args[0]);
|
||||||
|
String story = args[1];
|
||||||
|
long duration = Long.parseLong(args[2]);
|
||||||
|
network.start();
|
||||||
|
Thread poller = new Thread(() -> {
|
||||||
|
while (true) {
|
||||||
|
poll();
|
||||||
|
try {
|
||||||
|
Thread.sleep(2);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
poller.setDaemon(true);
|
||||||
|
poller.start();
|
||||||
|
long end = network.start + duration;
|
||||||
|
|
||||||
|
switch (story) {
|
||||||
|
case "exchange": {
|
||||||
|
server(() -> {
|
||||||
|
ServerSocket listener = new ServerSocket(network.system(SERVER), 80, IpPaket.TCP, new ArrayList<>());
|
||||||
|
Socket accepted = (Socket) call("server oeffnen", listener::oeffnen);
|
||||||
|
watch("server", accepted);
|
||||||
|
call("server empfangen", accepted::empfangen);
|
||||||
|
call("server senden", () -> {
|
||||||
|
accepted.senden(repeat("x", 3000));
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
while (!((TCPSocket) accepted).getStateAsString().equals("CLOSE_WAIT")) Thread.sleep(2);
|
||||||
|
Thread.sleep(1000);
|
||||||
|
call("server schliessen", () -> {
|
||||||
|
accepted.schliessen();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
Thread.sleep(500);
|
||||||
|
TCPSocket client = new TCPSocket(network.system(CLIENT), "192.168.0.10", 80);
|
||||||
|
watch("client", client);
|
||||||
|
call("client verbinden", () -> {
|
||||||
|
client.verbinden();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
call("client senden", () -> {
|
||||||
|
client.senden("GET /");
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
call("client empfangen", client::empfangen);
|
||||||
|
call("client schliessen", () -> {
|
||||||
|
client.schliessen();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "closedPort": {
|
||||||
|
Thread.sleep(500);
|
||||||
|
TCPSocket client = new TCPSocket(network.system(OTHER_CLIENT), "192.168.0.10", 81);
|
||||||
|
watch("client", client);
|
||||||
|
call("client verbinden", () -> {
|
||||||
|
client.verbinden();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case "lostData": {
|
||||||
|
server(() -> {
|
||||||
|
ServerSocket listener = new ServerSocket(network.system(SERVER), 80, IpPaket.TCP, new ArrayList<>());
|
||||||
|
Socket accepted = (Socket) call("server oeffnen", listener::oeffnen);
|
||||||
|
watch("server", accepted);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
Thread.sleep(500);
|
||||||
|
TCPSocket client = new TCPSocket(network.system(CLIENT), "192.168.0.10", 80);
|
||||||
|
watch("client", client);
|
||||||
|
call("client verbinden", () -> {
|
||||||
|
client.verbinden();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
Thread.sleep(500);
|
||||||
|
event("loss on");
|
||||||
|
Verbindung.setDrop(true);
|
||||||
|
call("client senden", () -> {
|
||||||
|
client.senden("verloren");
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
Verbindung.setDrop(false);
|
||||||
|
event("loss off");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("unknown story " + story);
|
||||||
|
}
|
||||||
|
|
||||||
|
long rest = end - System.currentTimeMillis();
|
||||||
|
if (rest > 0) Thread.sleep(rest);
|
||||||
|
poll();
|
||||||
|
|
||||||
|
ScenarioNetwork.Json out = new ScenarioNetwork.Json();
|
||||||
|
out.open('{');
|
||||||
|
network.writeFrames(out);
|
||||||
|
synchronized (TcpRun.class) {
|
||||||
|
out.key("events").open('[');
|
||||||
|
for (Object[] each : events) out.open('[').number((Long) each[0]).string((String) each[1]).close(']');
|
||||||
|
out.close(']');
|
||||||
|
out.key("states").open('{');
|
||||||
|
for (Map.Entry<String, List<Object[]>> entry : states.entrySet()) {
|
||||||
|
out.key(entry.getKey()).open('[');
|
||||||
|
for (Object[] each : entry.getValue()) out.open('[').number((Long) each[0]).string((String) each[1]).close(']');
|
||||||
|
out.close(']');
|
||||||
|
}
|
||||||
|
out.close('}');
|
||||||
|
}
|
||||||
|
out.close('}');
|
||||||
|
network.stop();
|
||||||
|
ScenarioNetwork.write(args[3], out);
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user