Skip to content

Commit f112083

Browse files
authored
feat: show IP addresses in packet info (#62)
This PR adds packet data to `Packet`, and shows part of that info in the right bar.
1 parent ae060b8 commit f112083

File tree

6 files changed

+111
-44
lines changed

6 files changed

+111
-44
lines changed

src/graphics/renderables/device_info.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Device } from "../../types/devices";
22
import { DeviceType } from "../../types/devices/device";
3+
import { RoutingTableEntry } from "../../types/graphs/datagraph";
34
import { ViewGraph } from "../../types/graphs/viewgraph";
45
import { sendPacket } from "../../types/packet";
56
import {
@@ -69,7 +70,7 @@ export class DeviceInfo extends StyledInfo {
6970
);
7071
}
7172

72-
addRoutingTable(entries: { ip: string; mask: string; iface: string }[]) {
73+
addRoutingTable(entries: RoutingTableEntry[]) {
7374
const rows = entries.map((entry) => [entry.ip, entry.mask, entry.iface]);
7475

7576
const dynamicTable = createToggleTable(

src/types/devices/device.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
TextStyle,
77
Text,
88
} from "pixi.js";
9-
import { ViewGraph } from "./../graphs/viewgraph";
9+
import { EdgeId, ViewGraph } from "./../graphs/viewgraph";
1010
import {
1111
deselectElement,
1212
refreshElement,
@@ -17,6 +17,7 @@ import { Colors, ZIndexLevels } from "../../utils";
1717
import { Position } from "../common";
1818
import { DeviceInfo } from "../../graphics/renderables/device_info";
1919
import { IpAddress } from "../../packets/ip";
20+
import { DeviceId } from "../graphs/datagraph";
2021

2122
export const DEVICE_SIZE = 20;
2223

@@ -33,7 +34,7 @@ export enum DeviceType {
3334
}
3435

3536
export abstract class Device extends Sprite {
36-
readonly id: number;
37+
readonly id: DeviceId;
3738
readonly viewgraph: ViewGraph;
3839
connections = new Map<number, number>();
3940

@@ -90,19 +91,19 @@ export abstract class Device extends Sprite {
9091
this.addChild(idText); // Add the ID text as a child of the device
9192
}
9293

93-
getConnections(): { edgeId: number; adyacentId: number }[] {
94+
getConnections(): { edgeId: EdgeId; adyacentId: DeviceId }[] {
9495
return Array.from(this.connections.entries()).map(
9596
([edgeId, adyacentId]) => {
9697
return { edgeId, adyacentId };
9798
},
9899
);
99100
}
100101

101-
addConnection(edgeId: number, adyacentId: number) {
102+
addConnection(edgeId: EdgeId, adyacentId: DeviceId) {
102103
this.connections.set(edgeId, adyacentId);
103104
}
104105

105-
removeConnection(id: number) {
106+
removeConnection(id: EdgeId) {
106107
this.connections.delete(id);
107108
}
108109

src/types/devices/router.ts

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,10 @@ export class Router extends Device {
1919
showInfo(): void {
2020
const info = new DeviceInfo(this);
2121
info.addField("IP Address", this.ip.octets.join("."));
22-
info.addRoutingTable(this.generate_routing_table());
22+
info.addRoutingTable(this.viewgraph.getRoutingTable(this.id));
2323
RightBar.getInstance().renderInfo(info);
2424
}
2525

26-
generate_routing_table(): { ip: string; mask: string; iface: string }[] {
27-
const routingTableEntries: { ip: string; mask: string; iface: string }[] =
28-
[];
29-
30-
this.getConnections().forEach(({ edgeId, adyacentId }) => {
31-
const connectedDevice = this.viewgraph.getDevice(adyacentId);
32-
if (connectedDevice) {
33-
const ip = connectedDevice.ip.toString();
34-
const mask = connectedDevice.ipMask.toString();
35-
// Generate interface name based on edge ID
36-
const iface = `eth${edgeId}`;
37-
routingTableEntries.push({ ip, mask, iface });
38-
}
39-
});
40-
return routingTableEntries;
41-
}
42-
4326
getLayer(): Layer {
4427
return Layer.Network;
4528
}

src/types/graphs/datagraph.ts

Lines changed: 59 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,25 @@ interface CommonGraphNode {
1313

1414
interface RouterGraphNode extends CommonGraphNode {
1515
type: DeviceType.Router;
16+
routingTable: RoutingTableEntry[];
17+
}
18+
19+
export interface RoutingTableEntry {
20+
ip: string;
21+
mask: string;
22+
iface: string;
23+
}
24+
25+
// Typescript type guard
26+
export function isRouter(node: GraphNode): node is RouterGraphNode {
27+
return node.type === DeviceType.Router;
1628
}
1729

1830
export type GraphNode = CommonGraphNode | RouterGraphNode;
1931

20-
export interface GraphDataNode {
32+
export type GraphDataNode = CommonDataNode | RouterDataNode;
33+
34+
interface CommonDataNode {
2135
id: DeviceId;
2236
x: number;
2337
y: number;
@@ -27,6 +41,11 @@ export interface GraphDataNode {
2741
connections: DeviceId[];
2842
}
2943

44+
interface RouterDataNode extends CommonDataNode {
45+
type: DeviceType.Router;
46+
routingTable: RoutingTableEntry[];
47+
}
48+
3049
export type GraphData = GraphDataNode[];
3150

3251
export interface NewDevice {
@@ -49,11 +68,7 @@ export class DataGraph {
4968
console.log(nodeData);
5069
const connections = new Set(nodeData.connections);
5170
const graphNode: GraphNode = {
52-
x: nodeData.x,
53-
y: nodeData.y,
54-
type: nodeData.type,
55-
ip: nodeData.ip,
56-
mask: nodeData.mask,
71+
...nodeData,
5772
connections: connections,
5873
};
5974
dataGraph.addDevice(nodeData.id, graphNode);
@@ -66,15 +81,20 @@ export class DataGraph {
6681

6782
// Serialize nodes
6883
this.getDevices().forEach(([id, info]) => {
69-
graphData.push({
70-
id: id,
84+
const graphNode: GraphDataNode = {
85+
id,
7186
x: info.x,
7287
y: info.y,
7388
type: info.type, // Save the device type (Router, Host)
7489
ip: info.ip,
7590
mask: info.mask,
7691
connections: Array.from(info.connections.values()),
77-
});
92+
};
93+
if (isRouter(info)) {
94+
graphData.push({ ...graphNode, routingTable: info.routingTable });
95+
} else {
96+
graphData.push(graphNode);
97+
}
7898
});
7999
return graphData;
80100
}
@@ -85,6 +105,7 @@ export class DataGraph {
85105
const graphnode: GraphNode = {
86106
...deviceInfo,
87107
connections: new Set<number>(),
108+
routingTable: [],
88109
};
89110
this.devices.set(id, graphnode);
90111
console.log(`Device added with ID ${id}`);
@@ -114,23 +135,47 @@ export class DataGraph {
114135
);
115136
return;
116137
}
117-
if (!this.devices.has(n1Id)) {
138+
const device1 = this.devices.get(n1Id);
139+
const device2 = this.devices.get(n2Id);
140+
if (!device1) {
118141
console.warn(`Device with ID ${n1Id} does not exist in devices.`);
119142
return;
120143
}
121-
if (!this.devices.has(n2Id)) {
144+
if (!device2) {
122145
console.warn(`Device with ID ${n2Id} does not exist in devices.`);
123146
return;
124147
// Check if an edge already exists between these two devices
125148
}
126-
if (this.devices.get(n1Id).connections.has(n2Id)) {
149+
if (device1.connections.has(n2Id)) {
127150
console.warn(
128151
`Connection between ID ${n1Id} and ID ${n2Id} already exists.`,
129152
);
130153
return;
131154
}
132-
this.devices.get(n1Id).connections.add(n2Id);
133-
this.devices.get(n2Id).connections.add(n1Id);
155+
device1.connections.add(n2Id);
156+
device2.connections.add(n1Id);
157+
158+
if (isRouter(device1)) {
159+
if (!device1.routingTable) {
160+
device1.routingTable = [];
161+
}
162+
device1.routingTable.push({
163+
ip: device2.ip.toString(),
164+
mask: device2.mask,
165+
iface: `eth${n2Id}`,
166+
});
167+
}
168+
169+
if (isRouter(device2)) {
170+
if (!device2.routingTable) {
171+
device2.routingTable = [];
172+
}
173+
device2.routingTable.push({
174+
ip: device1.ip.toString(),
175+
mask: device1.mask,
176+
iface: `eth${n1Id}`,
177+
});
178+
}
134179

135180
console.log(
136181
`Connection created between devices ID: ${n1Id} and ID: ${n2Id}`,

src/types/graphs/viewgraph.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Device } from "./../devices/index"; // Import the Device class
22
import { Edge } from "./../edge";
3-
import { DataGraph, DeviceId } from "./datagraph";
3+
import { DataGraph, DeviceId, isRouter } from "./datagraph";
44
import { Viewport } from "../../graphics/viewport";
55
import { Layer } from "../devices/device";
66
import { createDevice } from "../devices/utils";
@@ -226,6 +226,14 @@ export class ViewGraph {
226226
return this.viewport;
227227
}
228228

229+
getRoutingTable(id: DeviceId) {
230+
const device = this.datagraph.getDevice(id);
231+
if (!device || !isRouter(device)) {
232+
return [];
233+
}
234+
return device.routingTable;
235+
}
236+
229237
// En ViewGraph
230238
getEdge(edgeId: EdgeId): Edge | undefined {
231239
return this.edges.get(edgeId);

src/types/packet.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { circleGraphicsContext, Colors, ZIndexLevels } from "../utils";
1010
import { RightBar, StyledInfo } from "../graphics/right_bar";
1111
import { Position } from "./common";
1212
import { ViewGraph } from "./graphs/viewgraph";
13+
import { EmptyPayload, IPv4Packet } from "../packets/ip";
14+
import { EchoRequest } from "../packets/icmp";
1315

1416
const contextPerPacketType: Record<string, GraphicsContext> = {
1517
IP: circleGraphicsContext(Colors.Green, 0, 0, 5),
@@ -19,7 +21,7 @@ const contextPerPacketType: Record<string, GraphicsContext> = {
1921
const highlightedPacketContext = circleGraphicsContext(Colors.Violet, 0, 0, 6);
2022

2123
export class Packet extends Graphics {
22-
speed: number;
24+
speed = 200;
2325
progress = 0;
2426
currentPath: Edge[];
2527
currentEdge: Edge;
@@ -29,6 +31,8 @@ export class Packet extends Graphics {
2931
sourceId: number;
3032
destinationId: number;
3133

34+
rawPacket: IPv4Packet;
35+
3236
static animationPaused = false;
3337

3438
static pauseAnimation() {
@@ -41,7 +45,7 @@ export class Packet extends Graphics {
4145

4246
constructor(
4347
type: string,
44-
speed: number,
48+
rawPacket: IPv4Packet,
4549
sourceid: number,
4650
destinationid: number,
4751
) {
@@ -52,7 +56,7 @@ export class Packet extends Graphics {
5256
this.context = contextPerPacketType[this.type];
5357
this.zIndex = ZIndexLevels.Packet;
5458

55-
this.speed = speed;
59+
this.rawPacket = rawPacket;
5660
this.sourceId = sourceid;
5761
this.destinationId = destinationid;
5862

@@ -81,6 +85,11 @@ export class Packet extends Graphics {
8185
info.addField("Type", this.type);
8286
info.addField("Source ID", this.sourceId.toString());
8387
info.addField("Destination ID", this.destinationId.toString());
88+
info.addField("Source IP Address", this.rawPacket.sourceAddress.toString());
89+
info.addField(
90+
"Destination IP Address",
91+
this.rawPacket.destinationAddress.toString(),
92+
);
8493

8594
rightbar.renderInfo(info);
8695
}
@@ -167,7 +176,6 @@ export function sendPacket(
167176
console.log(
168177
`Sending ${packetType} packet from ${originId} to ${destinationId}`,
169178
);
170-
const speed = 200; // Velocidad en píxeles por segundo
171179

172180
const pathEdgeIds = viewgraph.getPathBetween(originId, destinationId);
173181

@@ -178,8 +186,29 @@ export function sendPacket(
178186
return;
179187
}
180188

189+
const originDevice = viewgraph.getDevice(originId);
190+
const destinationDevice = viewgraph.getDevice(destinationId);
191+
181192
const pathEdges = pathEdgeIds.map((id) => viewgraph.getEdge(id));
182193

183-
const packet = new Packet(packetType, speed, originId, destinationId);
194+
// TODO: allow user to choose which payload to send
195+
let payload;
196+
switch (packetType) {
197+
case "IP":
198+
payload = new EmptyPayload();
199+
break;
200+
case "ICMP":
201+
payload = new EchoRequest(0);
202+
break;
203+
default:
204+
console.warn("Tipo de paquete no reconocido");
205+
return;
206+
}
207+
const rawPacket = new IPv4Packet(
208+
originDevice.ip,
209+
destinationDevice.ip,
210+
payload,
211+
);
212+
const packet = new Packet(packetType, rawPacket, originId, destinationId);
184213
packet.animateAlongPath(pathEdges, originId);
185214
}

0 commit comments

Comments
 (0)