diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7..e470994 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,6 @@
+
\ No newline at end of file
diff --git a/images/icons8-letter-100.png b/images/icons8-letter-100.png
new file mode 100644
index 0000000..a193ea3
Binary files /dev/null and b/images/icons8-letter-100.png differ
diff --git a/images/icons8-letter-50.png b/images/icons8-letter-50.png
new file mode 100644
index 0000000..ad4e42d
Binary files /dev/null and b/images/icons8-letter-50.png differ
diff --git a/images/icons8-pc-50.png b/images/icons8-pc-50.png
new file mode 100644
index 0000000..f4207fb
Binary files /dev/null and b/images/icons8-pc-50.png differ
diff --git a/images/icons8-router-symbol-100.png b/images/icons8-router-symbol-100.png
new file mode 100644
index 0000000..d14b4bc
Binary files /dev/null and b/images/icons8-router-symbol-100.png differ
diff --git a/images/icons8-router-symbol-50.png b/images/icons8-router-symbol-50.png
new file mode 100644
index 0000000..757788a
Binary files /dev/null and b/images/icons8-router-symbol-50.png differ
diff --git a/images/pc_icon.png b/images/pc_icon.png
new file mode 100644
index 0000000..293925c
Binary files /dev/null and b/images/pc_icon.png differ
diff --git a/images/router_icon.png b/images/router_icon.png
new file mode 100644
index 0000000..e1eda2b
Binary files /dev/null and b/images/router_icon.png differ
diff --git a/network_protocol_simulation.iml b/network_protocol_simulation.iml
index c3dc060..1a35fa4 100644
--- a/network_protocol_simulation.iml
+++ b/network_protocol_simulation.iml
@@ -4,6 +4,8 @@
+
+
@@ -17,5 +19,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Device.java b/src/Device.java
index 5dfe7c0..ce7972c 100644
--- a/src/Device.java
+++ b/src/Device.java
@@ -1,7 +1,7 @@
import java.util.ArrayList;
abstract public class Device {
- // Abstract class for holding data memebers and methods that are common within the Router and PC child classes.
+ // Abstract class for holding data members and methods that are common within the Router and PC child classes.
private String name; // Name of the device
private ARPTable arpTable = new ARPTable(); // ARP table for the device.
@@ -23,5 +23,4 @@ public Device(String name) {
public void setNICList(ArrayList nicList) { this.nicList = nicList; }
public ArrayList getNICList() { return this.nicList; }
-
}
\ No newline at end of file
diff --git a/src/IPAddress.java b/src/IPAddress.java
index fc7a280..7189c67 100644
--- a/src/IPAddress.java
+++ b/src/IPAddress.java
@@ -109,7 +109,7 @@ public boolean equals(Object object) {
if(object == null || this.getClass() != object.getClass()) return false;
// Cast the object to the SubnetMask object class.
IPAddress ipAddress = (IPAddress) object;
- // Check if all of the subnet mask values match, if not then return false.
+ // Check if all the subnet mask values match, if not then return false.
if(this.ipAddress[0] != ipAddress.getIpAddress()[0]) return false;
if(this.ipAddress[1] != ipAddress.getIpAddress()[1]) return false;
if(this.ipAddress[2] != ipAddress.getIpAddress()[2]) return false;
@@ -117,4 +117,4 @@ public boolean equals(Object object) {
// Once all conditions are met, then the objects equal.
return true;
}
-}
\ No newline at end of file
+}
diff --git a/src/InfoField.java b/src/InfoField.java
new file mode 100644
index 0000000..38731d0
--- /dev/null
+++ b/src/InfoField.java
@@ -0,0 +1,57 @@
+import javax.swing.*;
+import java.awt.*;
+
+public class InfoField extends JPanel {
+ private JLabel label;
+ private JTextField textField;
+
+ InfoField(String labelText, String textFieldText) {
+ super.setLayout(new GridLayout(1, 2));
+ super.setBorder(BorderFactory.createLineBorder(Color.lightGray));
+
+ this.label = new JLabel(labelText);
+ this.label.setHorizontalAlignment(SwingConstants.LEFT);
+ super.add(label);
+
+ this.textField = new JTextField(textFieldText);
+ super.add(textField);
+ }
+
+ InfoField(String labelTest) {
+ super.setLayout(new GridLayout(1, 2));
+ super.setBorder(BorderFactory.createLineBorder(Color.lightGray));
+
+ this.label = new JLabel(labelTest);
+ this.label.setHorizontalAlignment(SwingConstants.LEFT);
+ super.add(label);
+ }
+
+ public void setLabelText(String labelText) {
+ this.label.setText(labelText);
+ updateComponents();
+ }
+
+ public void setTextFieldText(String textFieldText) {
+ this.textField.setText(textFieldText);
+ updateComponents();
+ }
+
+ public void setEditable(boolean editable) {
+ this.textField.setEditable(editable);
+ }
+
+ public JLabel getLabel() {
+ return label;
+ }
+
+ public JTextField getTextField() {
+ return textField;
+ }
+
+ private void updateComponents() {
+ super.removeAll();
+ super.add(label);
+ super.add(textField);
+ }
+
+}
diff --git a/src/Line.java b/src/Line.java
new file mode 100644
index 0000000..bc69186
--- /dev/null
+++ b/src/Line.java
@@ -0,0 +1,23 @@
+import javax.swing.*;
+import java.awt.*;
+
+public class Line extends JPanel {
+ private int x1, y1, x2, y2;
+ private Color color;
+
+ public Line(int x1, int y1, int x2, int y2, Color color) {
+ this.x1 = x1;
+ this.y1 = y1;
+ this.x2 = x2;
+ this.y2 = y2;
+ this.color = color;
+ }
+
+ // Method to draw the line
+ public void draw(Graphics g) {
+ Graphics2D g2D = (Graphics2D) g;
+ g2D.setColor(color);
+ g2D.setStroke(new BasicStroke(5)); // Set line thickness
+ g2D.drawLine(x1, y1, x2, y2);
+ }
+}
diff --git a/src/MACAddress.java b/src/MACAddress.java
index b01b8d2..3a840ae 100644
--- a/src/MACAddress.java
+++ b/src/MACAddress.java
@@ -1,5 +1,3 @@
-// TODO: Need to add subnet for PC.
-
import java.util.Random;
public class MACAddress {
diff --git a/src/Main.java b/src/Main.java
index 099e1c6..eb09678 100644
--- a/src/Main.java
+++ b/src/Main.java
@@ -1,626 +1,107 @@
+// imports the gui package and the Frame class into this class.
+
+import javax.swing.*;
+import java.awt.*;
import java.util.ArrayList;
import java.util.Scanner;
+import java.util.concurrent.atomic.AtomicReference;
-// delete this comment
public class Main {
public static void main(String[] args) {
- // All the created PCs within the simulation.
- ArrayList pcList = new ArrayList<>();
- // All the created Routers within the simulation.
- ArrayList routerList = new ArrayList<>();
- // Keeps track of all the default gateways that have been assigned to a PC.
- ArrayList assignedDefaultGatewayList = new ArrayList<>();
-
- System.out.print("########################################\n");
- System.out.print("Welcome to the PING protocol simulation.\n");
- System.out.print("########################################\n\n");
-
- // Variables used for menu navigation and options.
- String menu = "main"; // Menu (main, pc, or router)
- int exit = 0; // When to exit the program
- int option = -1; // User selected menu option
- int pcSelection = -1; // pc index for pcList selection
- int routerSelection = -1; // router index for routerList selection
- Scanner scanner = new Scanner(System.in); // Scanner for user input
- PingProtocol pingProtocol = new PingProtocol(); // Instance used for simulating ping between devices.
-
- // Loop until the user decides to exit.
- do {
- if (menu.equals("main")) {
- // Display the main menu.
- displayMainMenu(pcList, routerList);
-
- // Checks whether the scanner had received an int or not, if it doesn't it prnts the below.
- while (!scanner.hasNextInt()) {
- System.out.println("Invalid input. Please enter a valid number.");
- scanner.next(); // Consume the invalid input
- }
- option = scanner.nextInt(); // Read the user selection
-
- // Handle user selection for the main menu.
- switch (option) {
- case 1:
- // Create PC and add it to the list of PC's
- pcList.add(createPC());
- break;
-
- case 2:
- // Delete PC
- // This will need to show a list of PC's where the user can select what PC to delete.
- System.out.println("Select a PC to delete");
- // Checks whether the scanner had received an int or not, if it doesn't it prnts the below.
- while (!scanner.hasNextInt()) {
- System.out.println("Invalid input. Please enter a valid number.");
- scanner.next(); // Consume the invalid input
- }
- // -1 because it is based on the index of the ArrayList of the PC.
- pcSelection = scanner.nextInt() - 1;
-
- // Attempt to remove a PC from the pcList, and handle the error if there is one.
- try {
- pcList.remove(pcSelection);
- } catch (IndexOutOfBoundsException e) {
- System.out.println("PC does not exist");
- }
-
- break;
-
- case 3:
- // Select PC
- System.out.println("Select a PC from the list");
- // Checks whether the scanner had received an int or not, if it doesn't it prnts the below.
- while (!scanner.hasNextInt()) {
- System.out.println("Invalid input. Please enter a valid number.");
- scanner.next(); // Consume the invalid input
- }
- pcSelection = scanner.nextInt() - 1; // convert input to 0 based index.
-
- try {
- // Check if the PC exists within the pcList.
- pcList.get(pcSelection);
- menu = "pc"; // Switch to PC menu
- } catch (IndexOutOfBoundsException e) {
- System.out.println("PC does not exist");
- menu = "main"; // Switch back to main menu if error
- }
-
- // Reset the option for the PC menu.
- option = -1;
- break;
-
- case 4:
- // Create a Router
- routerList.add(createRouter());
- break;
-
- case 5:
- // Delete a Router
- System.out.println("Select a Router to delete");
- // Checks whether the scanner had received an int or not, if it doesn't it prnts the below.
- while (!scanner.hasNextInt()) {
- System.out.println("Invalid input. Please enter a valid number.");
- scanner.next(); // Consume the invalid input
- }
- routerSelection = scanner.nextInt() - 1;
-
- // Attempt remove the selected Router.
- try {
- routerList.remove(routerSelection);
- } catch (IndexOutOfBoundsException e) {
- System.out.println("Router does not exist");
- }
-
- break;
-
- case 6:
- // Select a Router
- System.out.println("Select a Router from the list");
- // Checks whether the scanner had received an int or not, if it doesn't it prnts the below.
- while (!scanner.hasNextInt()) {
- System.out.println("Invalid input. Please enter a valid number.");
- scanner.next(); // Consume the invalid input
- }
- routerSelection = scanner.nextInt() - 1;
-
- try {
- // Check if the Router exists within the routerList.
- routerList.get(routerSelection);
- menu = "router";
- } catch (IndexOutOfBoundsException e) {
- System.out.println("Router does not exist");
- menu = "main";
- }
-
- // Reset the option for the PC menu.
- option = -1;
- break;
-
- case 7:
- // Exit the program.
- System.out.println("Bye");
- exit = 1;
- break;
-
- default:
- System.out.println("Invalid option");
- break;
- }
-
- } else if (menu.equals("pc")) {
- displayPCMenu(pcList, pcSelection);
- // Checks whether the scanner had received an int or not, if it doesn't it prnts the below.
- while (!scanner.hasNextInt()) {
- System.out.println("Invalid input. Please enter a valid number.");
- scanner.next(); // Consume the invalid input
- }
- option = scanner.nextInt();
- // Removes any new line characters that nextInt() didn't use. If not then any nextLine() function used
- // on the scanner, will automatically have \n as its input.
- scanner.nextLine();
- PC pc = pcList.get(pcSelection);
-
- switch (option) {
- // Change name
- case 1:
- System.out.println("Enter the new name for the PC");
- String name = scanner.nextLine();
- pc.setName(name);
- break;
-
- // Change IP address
- case 2:
- System.out.println("Enter the new IP for the PC");
- String ipAddressString = scanner.nextLine();
- // Create a new instance IPAddress with the inputted ip address String
- IPAddress ipAddress = createIP(ipAddressString);
-
- System.out.println("Enter the subnet mask for the PC");
- String subnetMaskString = scanner.nextLine();
- // Create a new instance SubnetMask with the inputted subnet mask String
- SubnetMask subnetMask = createSubnetMask(subnetMaskString);
-
- // Set the port with the ip address and the subnet mask for the pc.
- pc.setPortFA00(ipAddress, subnetMask);
- break;
-
- // Set default gateway for the PC
- case 3:
- System.out.println("Enter the IP for the default gateway");
- String defaultGatewayString = scanner.nextLine();
- // Create a default gateway ip address for the pc.
- IPAddress defaultGatewayIP = createIP(defaultGatewayString);
-
- System.out.println("Enter the subnet mask for the default gateway");
- // Create a default gateway subnet mask for the pc.
- String defaultGatewaySubnetMaskString = scanner.nextLine();
- SubnetMask defaultGatewaySubnet = createSubnetMask(defaultGatewaySubnetMaskString);
-
- if(!checkDefaultGatewayExists(routerList, defaultGatewayIP, defaultGatewaySubnet)) {
- // Checks to see whether the default gateway exists within the network.
- System.out.println("The provided default gateway does not exist within the network.");
- } else if (checkDefaultGatewayAssigned(assignedDefaultGatewayList, defaultGatewayIP, defaultGatewaySubnet)) {
- // Checks if the default gateway is not assigned, to another PC.
- System.out.println("The provided default gateway is already assigned to another device.");
- } else {
- // Sets the default gateway for the PC.
- pc.setDefaultGateway(defaultGatewayIP, defaultGatewaySubnet);
- // Add the PC to the list of assigned default gateways, only if the PC is not already in the
- // list
- if(!assignedDefaultGatewayList.contains(pc)) {
- assignedDefaultGatewayList.add(pc);
- }
- }
-
- break;
-
- case 4:
- // Start the ping process with another device.
- System.out.println("Enter the IP address you want to ping to");
- // Creates the destination IP address from the user input.
- IPAddress destinationIP = new IPAddress(scanner.nextLine());
- // retreive the index based on the destination Ip address from the pcList
- int destinationPCIndex = getIndexFromPCListWithIP(destinationIP, pcList);
- // If ther destinationPCIndex is correctly returned, it means it exists.
- if(destinationPCIndex != -1) {
- pingProtocol.ping(pc, pcList.get(destinationPCIndex), pcList, routerList);
- } else {
- System.out.println("Destination PC does not exist");
- }
- break;
-
- case 5:
- // Return to the main menu.
- menu = "main";
- break;
-
- default:
- System.out.println("Invalid option");
- break;
- }
- } else if (menu.equals("router")) {
- displayRouterMenu(routerList, routerSelection);
- // Checks whether the scanner had received an int or not, if it doesn't it prnts the below.
- while (!scanner.hasNextInt()) {
- System.out.println("Invalid input. Please enter a valid number.");
- scanner.next(); // Consume the invalid input
- }
- option = scanner.nextInt();
- // Removes any new line characters that nextInt() didn't use. If not then any nextLine() function used
- // on the scanner, will automatically have \n as its input.
- scanner.nextLine();
- Router router = routerList.get(routerSelection);
-
- switch (option) {
- case 1:
- System.out.println("Enter the new name for the router");
- String name = scanner.nextLine();
- router.setName(name);
- break;
-
- // cases 2 to case 4 are used for creating the IP address for the ports of the router, as well
- // as the subnet mask.
- case 2:
- System.out.println("Enter IP address for GigabitEthernet 0/0");
- String ipAddress00String = scanner.nextLine();
- IPAddress ipAddress00 = createIP(ipAddress00String);
-
- System.out.println("Enter the subnet mask for GigabitEthernet 0/0");
- String subnetMask00String = scanner.nextLine();
- SubnetMask subnetMask00 = createSubnetMask(subnetMask00String);
-
- router.setPortGig00(ipAddress00, subnetMask00);
- break;
-
- case 3:
- System.out.println("Enter IP address for GigabitEthernet 0/1");
- String ipAddress01String = scanner.nextLine();
- IPAddress ipAddress01 = createIP(ipAddress01String);
-
- System.out.println("Enter the subnet mask for GigabitEthernet 0/1");
- String subnetMask01String = scanner.nextLine();
- SubnetMask subnetMask01 = createSubnetMask(subnetMask01String);
-
- router.setPortGig01(ipAddress01, subnetMask01);
- break;
-
- case 4:
- System.out.println("Enter IP address for GigabitEthernet 0/2");
- String ipAddress02String = scanner.nextLine();
- IPAddress ipAddress02 = createIP(ipAddress02String);
-
- System.out.println("Enter the subnet mask for GigabitEthernet 0/2");
- String subnetMask02String = scanner.nextLine();
- SubnetMask subnetMask02 = createSubnetMask(subnetMask02String);
-
- router.setPortGig02(ipAddress02, subnetMask02);
- break;
+ JFrame frame = new JFrame("OSPF Simulation");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // Close the application, when pressing X (all frames close)
+ frame.setResizable(false);
+ frame.setSize(600, 300);
+ frame.setLayout(new GridLayout(0, 1)); // rows=0, cols=1. Makes it vertical.
- case 5:
- // Go back to the main menu
- menu = "main";
- break;
- }
- }
- // Check if user wants to exit program.
- } while (exit == 0);
- }
-
- public static IPAddress createIP(String ipAddressString) {
- // tries to create an IPAddress, if it doesn't work then it will catch
- // the error from within the class and prints it out here.
- boolean valid;
-
- do {
- try {
- new IPAddress(ipAddressString);
- valid = true;
- } catch (IllegalArgumentException e) {
- Scanner scanner = new Scanner(System.in);
- System.out.print("Please enter a valid IP address: ");
- ipAddressString = scanner.nextLine();
- valid = false;
- }
- } while (!valid);
+ JLabel welcomeLabel = new JLabel("""
+
+ Welcome to the OSPF simulation protocol!
+ Please select whether you want to create a custom network or a preconfigured network.
+ """, SwingConstants.CENTER); // html is used to add line break
+ welcomeLabel.setBackground(Color.lightGray);
+ welcomeLabel.setOpaque(true);
- return new IPAddress(ipAddressString);
- }
-
- public static SubnetMask createSubnetMask(String subnetString) {
- // tries to create an IPAddress, if it doesn't work then it will catch
- // the error from within the class and prints it out here.
- boolean valid;
- do {
- try {
- new SubnetMask(subnetString);
- valid = true;
- } catch (IllegalArgumentException e) {
- Scanner scanner = new Scanner(System.in);
- System.out.print("Please enter a valid subnet mask: ");
- subnetString = scanner.nextLine();
- valid = false;
- }
- } while (!valid);
+ JButton customNetworkButton = new JButton("Custom Network");
+ Font networkButtonFont = new Font(customNetworkButton.getFont().getName(), Font.BOLD, 20);
+ customNetworkButton.setFont(networkButtonFont);
- return new SubnetMask(subnetString);
- }
+ JButton preconfiguredNetworkButton = new JButton("Preconfigured Network");
+ preconfiguredNetworkButton.setFont(networkButtonFont);
- public static PC createPC() {
- // this just prompts the user to enter the needed information for creating a PC. It will ask for the name, IP,
- // and subnet mask and create the object.
+ frame.add(welcomeLabel);
+ frame.add(customNetworkButton);
+ frame.add(preconfiguredNetworkButton);
+ frame.setVisible(true); // Make start_menu_frame visible
- Scanner scanner = new Scanner(System.in);
-
- System.out.print("Please enter the name for the PC: ");
- String name = scanner.nextLine();
-
- System.out.print("Please enter the IP address for " + name + ": ");
- String ipInput = scanner.nextLine();
- IPAddress ip = createIP(ipInput);
-
- System.out.println("Enter the subnet mask for the PC");
- String subnetMaskInput = scanner.nextLine();
- SubnetMask subnetMask = createSubnetMask(subnetMaskInput);
-
- return new PC(name, ip, subnetMask);
- }
+ JLabel customNetworkLabel = new JLabel("Custom Network");
- public static Router createRouter() {
- // this prompts the user to create the router with the input of its name only. The user can change the other
- // details of the router through different options.
- Scanner scanner = new Scanner(System.in);
+ preconfiguredNetworkButton.addActionListener(e -> {
+ System.out.println("Preconfigured network button pressed.");
- System.out.print("Please enter the name for the Router: ");
- String name = scanner.nextLine();
+ frame.remove(welcomeLabel);
+ frame.remove(customNetworkButton);
+ frame.remove(preconfiguredNetworkButton);
- return new Router(name);
- }
+ frame.setTitle("OSPF Simulation: Prebuilt Network");
+ frame.setSize(1200, 1000);
+ frame.setLayout(new GridLayout()); // rows=0, cols=1. Makes it vertical.
- public static void displayMainMenu(ArrayList pcList, ArrayList routerList) {
- // Options displayed for the user to choose on what actions they want to take.
- String[] menuOptions = {
- "Create PC ",
- "Delete PC ",
- "Select PC ",
- "Create Router",
- "Delete Router",
- "Select Router",
- "Exit Program "
- };
+ PreconfiguredNetworkPanel preconfiguredNetworkPanel = new PreconfiguredNetworkPanel();
+ frame.add(preconfiguredNetworkPanel);
+ preconfiguredNetworkPanel.setVisible(true);
+ });
- System.out.print("------------------------------------------------------------------------------------\n");
- System.out.println("Options \t\t\t| List of Devices (PC on Left, Router on Right)");
- System.out.print("------------------------------------------------------------------------------------\n");
+ customNetworkButton.addActionListener(e -> {
+ System.out.println("Custom network button pressed.");
- // Picks the largest array/list to iterate through and prints out all the options from the menu as well as
- // the devices to the right of the options.
- int max1 = Math.max(pcList.size(), menuOptions.length);
- int max2 = Math.max(max1, routerList.size());
- // Iterate through the largest array and print out the menu.
- for(int i = 0; i < max2; i++) {
- int lineNum = i + 1;
+ frame.remove(welcomeLabel);
+ frame.remove(customNetworkButton);
+ frame.remove(preconfiguredNetworkButton);
- if (i < menuOptions.length) {
- // This is for printing out the menu and the devices.
- System.out.print(lineNum + "." + " " + menuOptions[i] + "\t\t" + "|");
- }
- if (i < pcList.size()) {
- // This is for printing out the pc's only, once all the options are printed.
- PC pc = pcList.get(i);
- System.out.print(" " + lineNum + "." + " " + pc.getName());
- }
- if (i < routerList.size()) {
- // This is for printing out the router's only.
- Router router = routerList.get(i);
- System.out.print(" " + lineNum + "." + " " + router.getName());
- }
- // Print a new line after every line.
- System.out.println();
- }
+ frame.setTitle("OSPF Simulation: Custom Network");
+ frame.setSize(1000, 600);
+ frame.setLayout(new GridLayout()); // rows=0, cols=1. Makes it vertical.
- // Some space for user input and the menu.
- System.out.println();
+ frame.add(customNetworkLabel);
+ });
}
- public static void displayPCMenu(ArrayList pcList, Integer pcIndex) {
- // Options displayed for the user to choose on what actions they want to take.
- String[] menuOptions = {
- "Change PC name ",
- "Change FastEthernet 0/0 IP address ",
- "Change default gateway ",
- "Ping another device ",
- "Return to main menu "
- };
-
- String[] pcAttributes = {
- "Name: " + pcList.get(pcIndex).getName(),
- "FastEthernet 0/0 IP address: " + pcList.get(pcIndex).getPortFA00().getIpAddress(),
- "FastEthernet 0/0 subnet mask: " + pcList.get(pcIndex).getPortFA00().getSubnetMask(),
- "FastEthernet 0/0 MAC address: " + pcList.get(pcIndex).getPortFA00().getMacAddress(),
- "Default gateway IP address: " + pcList.get(pcIndex).getDefaultGatewayIPAddress(),
- "Default gateway subnet mask: " + pcList.get(pcIndex).getDefaultGatewaySubnetMask()
- };
-
- System.out.print("------------------------------------------------------------------------------------\n");
- System.out.println("Options \t\t\t\t\t\t\t\t| PC Information");
- System.out.print("------------------------------------------------------------------------------------\n");
-
- // Picks the largest array/list to iterate through and prints out all the options from the menu as well as
- // the devices to the right of the options.
- for(int i = 0; i < Math.max(pcAttributes.length, menuOptions.length); i++) {
- int lineNum = i + 1;
-
- if (i < menuOptions.length) {
- // This is for printing out the menu and the devices.
- System.out.print(lineNum + "." + " " + menuOptions[i] + "\t\t" + "|");
- } else {
- // Prints out the tabs and barrier for the menu within the router information
- System.out.print("\t\t\t\t\t\t\t\t\t\t\t" + "|");
- }
- if (i < pcAttributes.length) {
- // Prints out the PC details
- System.out.print(" " + pcAttributes[i]);
- }
- // Print a new line after every line.
- System.out.println();
+ /**
+ * Method for creating an array of JButton objects, with a name for each object.
+ * @param count The amount of Button objects in the array.
+ * @param name The text for the buttons + i, where is the current button being created.
+ * @return Array of JButton objects, with size count. With the text as: name + (count - 1), for each button.
+ */
+ private static JButton[] getJButtonArray(int count, String name) {
+ JButton[] buttons = new JButton[count];
+
+ // count-- is post decrement, meaning the current count variable is used, then it is decremented.
+ while (count-- > 0) {
+ buttons[count] = new JButton(name + (count));
}
-
- // Some space for user input and the menu.
- System.out.println();
+ return buttons;
}
- public static void displayRouterMenu(ArrayList routerList, Integer routerIndex) {
- // Options displayed for the user to choose on what actions they want to take.
- String[] menuOptions = {
- "Change Router name ",
- "Change GigabitEthernet 0/0 IP address ",
- "Change GigabitEthernet 0/1 IP address ",
- "Change GigabitEthernet 0/2 IP address ",
- "Return to main menu "
- };
-
- String[] routerAttributes = {
- "Name: " + routerList.get(routerIndex).getName(),
- "GigabitEthernet 0/0 IP address: " + routerList.get(routerIndex).getPortGig00().getIpAddress(),
- "GigabitEthernet 0/0 subnet mask: " + routerList.get(routerIndex).getPortGig00().getSubnetMask(),
- "GigabitEthernet 0/0 MAC address: " + routerList.get(routerIndex).getPortGig00().getMacAddress(),
- "GigabitEthernet 0/1 IP address: " + routerList.get(routerIndex).getPortGig01().getIpAddress(),
- "GigabitEthernet 0/1 subnet mask: " + routerList.get(routerIndex).getPortGig01().getSubnetMask(),
- "GigabitEthernet 0/1 MAC address: " + routerList.get(routerIndex).getPortGig01().getMacAddress(),
- "GigabitEthernet 0/2 IP address: " + routerList.get(routerIndex).getPortGig02().getIpAddress(),
- "GigabitEthernet 0/2 subnet mask: " + routerList.get(routerIndex).getPortGig02().getSubnetMask(),
- "GigabitEthernet 0/2 MAC address: " + routerList.get(routerIndex).getPortGig02().getMacAddress(),
- };
-
- System.out.print("------------------------------------------------------------------------------------\n");
- System.out.println("Options \t\t\t\t\t\t\t\t\t\t| Router Information");
- System.out.print("------------------------------------------------------------------------------------\n");
+ private static RouterButton[] getRouterButtonArray(int count, String name) {
+ RouterButton[] routers = new RouterButton[count];
- // Picks the largest array/list to iterate through and prints out all the options from the menu as well as
- // the devices to the right of the options.
- for(int i = 0; i < Math.max(routerAttributes.length, menuOptions.length); i++) {
- int lineNum = i + 1;
-
- if (i < menuOptions.length) {
- // This is for printing out the menu and the devices.
- System.out.print(lineNum + "." + " " + menuOptions[i] + "\t\t" + "|");
- } else {
- // Prints out the tabs and barrier for the menu within the router information
- System.out.print("\t\t\t\t\t\t\t\t\t\t\t\t" + "|");
- }
- if (i < routerAttributes.length) {
- // Prints out the Router details
- System.out.print(" " + routerAttributes[i]);
- }
- // Print a new line after every line.
- System.out.println();
+ // count-- is post decrement, meaning the current count variable is used, then it is decremented.
+ while (count-- > 0) {
+ routers[count] = new RouterButton(name + (count));
}
-
- // Some space for user input and the menu.
- System.out.println();
+ return routers;
}
- public static boolean gig00Match(ArrayList routerList, IPAddress defaultGatewayIPAddress, SubnetMask subnetMask) {
- // Checks if the router has any assigned subnet mask or IP address to its ports.
- for(Router router : routerList) {
- if((router.getPortGig00().getSubnetMask() == null) || (router.getPortGig00().getIpAddress() == null)) {
- // Move to the next router.
- continue;
- }
- // Checks if the subnet mask or the IP address equal to the required subnet mask and IP for the default
- // gateway.
- if((router.getPortGig00().getSubnetMask().equals(subnetMask)) && (router.getPortGig00().getIpAddress().equals(defaultGatewayIPAddress))) {
- System.out.println("Found match!");
- System.out.println("Router name:" + router.getName());
- System.out.println("Port name: " + router.getPortGig00().getName());
- System.out.println("Port IP address:" + router.getPortGig00().getIpAddress());
- System.out.println("Port Subnet Mask: " + router.getPortGig00().getSubnetMask());
- return true;
- }
+ private static PCButton[] getPCButtonArray(int count, String name, PreconfiguredNetworkPanel preconfiguredNetworkPanel) {
+ PCButton[] pcButtons = new PCButton[count];
- System.out.println(router.getPortGig00().getIpAddress() + " " + router.getPortGig00().getSubnetMask());
- System.out.println(defaultGatewayIPAddress + " " + subnetMask);
+ // count-- is post decrement, meaning the current count variable is used, then it is decremented.
+ while (count-- > 0) {
+ pcButtons[count] = new PCButton(name + (count), preconfiguredNetworkPanel);
}
-
- return false;
- }
-
- public static boolean gig01Match(ArrayList routerList, IPAddress defaultGatewayIPAddress, SubnetMask subnetMask) {
- // Checks if the router has any assigned subnet mask or IP address to its ports.
- for(Router router : routerList) {
- if((router.getPortGig01().getSubnetMask() == null) || (router.getPortGig01().getIpAddress() == null)) {
- // Move to the next router.
- continue;
- }
- // Checks if the subnet mask or the IP address equal to the required subnet mask and IP for the default
- // gateway.
- if((router.getPortGig01().getSubnetMask().equals(subnetMask)) && (router.getPortGig01().getIpAddress().equals(defaultGatewayIPAddress))) {
- System.out.println("Found match!");
- System.out.println("Router name: " + router.getName());
- System.out.println("Port name: " + router.getPortGig01().getName());
- System.out.println("Port IP address: " + router.getPortGig01().getIpAddress());
- System.out.println("Port Subnet Mask: " + router.getPortGig01().getSubnetMask());
- return true;
- }
-
- System.out.println(router.getPortGig01().getIpAddress() + " " + router.getPortGig01().getSubnetMask());
- }
-
- return false;
- }
-
- public static boolean gig02Match(ArrayList routerList, IPAddress defaultGatewayIPAddress, SubnetMask subnetMask) {
- // Checks if the router has any assigned subnet mask or IP address to its ports.
- for(Router router : routerList) {
- if((router.getPortGig02().getSubnetMask() == null) || (router.getPortGig02().getIpAddress() == null)) {
- // Move to the next router.
- continue;
- }
- // Checks if the subnet mask or the IP address equal to the required subnet mask and IP for the default
- // gateway.
- if((router.getPortGig02().getSubnetMask().equals(subnetMask)) && (router.getPortGig02().getIpAddress().equals(defaultGatewayIPAddress))) {
- System.out.println("Found match!");
- System.out.println("Router name:" + router.getName());
- System.out.println("Port name: " + router.getPortGig02().getName());
- System.out.println("Port IP address:" + router.getPortGig02().getIpAddress());
- System.out.println("Port Subnet Mask: " + router.getPortGig02().getSubnetMask());
- return true;
- }
-
- System.out.println(router.getPortGig02().getIpAddress() + " " + router.getPortGig02().getSubnetMask());
- }
-
- return false;
- }
-
- public static boolean checkDefaultGatewayExists(ArrayList routerList, IPAddress defaultGatewayIPAddress, SubnetMask subnetMask) {
- // This is just a holder for the previous gigXXMatch functions, it checks if any of the interfaces matched with the required
- // subnet mask and ip address.
- return gig00Match(routerList, defaultGatewayIPAddress, subnetMask) || (gig01Match(routerList, defaultGatewayIPAddress, subnetMask)) ||
- gig02Match(routerList, defaultGatewayIPAddress, subnetMask);
- }
-
- public static boolean checkDefaultGatewayAssigned(ArrayList assignedDefaultGatewayList, IPAddress ipAddress, SubnetMask subnetMask) {
- // This checks if a default gateway is already assigned to another PC for a given router interface.
- for(PC pc : assignedDefaultGatewayList) {
- if((pc.getDefaultGatewaySubnetMask().equals(subnetMask)) && (pc.getDefaultGatewayIPAddress().equals(ipAddress))) {
- return true;
- }
- }
-
- return false;
- }
-
- public static int getIndexFromPCListWithIP(IPAddress ip, ArrayList pcList) {
- // Search through all the PCs in the network and see if there is an available PC.
- for(int i = 0; i < pcList.size(); i++) {
- if(pcList.get(i).getNICList().get(0).getIpAddress().equals(ip)) {
- // return the index from the ArrayList
- return i;
- }
- }
-
- return -1;
+ return pcButtons;
}
}
\ No newline at end of file
diff --git a/src/NIC.java b/src/NIC.java
index 15d2507..a2d7d0d 100644
--- a/src/NIC.java
+++ b/src/NIC.java
@@ -1,16 +1,55 @@
public class NIC {
- // The name of an interface should not be changed once created.
- private final String name;
+ private Device assignedDevice;
+ private String type;
private IPAddress ipAddress;
private SubnetMask subNetMask;
- private final MACAddress macAddress = new MACAddress();
+ private MACAddress macAddress;
+ private NIC connection;
+ private NICManager nicManager = NICManager.getInstance();
+ // Default is always 0 for OSPF
+ private int priority = 0;
+ // Assuming that OSPF is always configured.
+ // States:
+ // 1. Down
+ // 2. Init
+ // 3. Two-way
+ // 4. ExStart
+ // 5. Exchange
+ // 6. Loading
+ // 7. Full
+ private String state = "Full";
+ // TODO: Placeholder, can change it to values between 20 and 40 seconds everytime the user
+ // looks at the value
+ private String deadTime = "00:00:31";
- public NIC(String name) {
- this.name = name;
+ public NIC(String type, Device assignedDevice) {
+ this.type = type;
+ this.assignedDevice = assignedDevice;
+ // Add the NIC to the NICManager to keep track of NICs automatically.
+ nicManager.addNIC(this);
+ setMacAddress();
}
- public String getName() {
- return name;
+ private void setMacAddress() {
+ int count = 10;
+ // create a MACAddress for the NIC, if it already exists, then keep creating one until it is unique, or if looped
+ // 10 times. 10 times to make sure it won't infinitely loop, the likelihood of generated 10 of the same MACAddresses
+ // is almost zero.
+ do {
+ macAddress = new MACAddress();
+ } while (nicManager.macExists(macAddress) && count-- > 0);
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public void setType(String type) {
+ if (type.equalsIgnoreCase("GigabitEthernet") || type.equalsIgnoreCase("FastEthernet")) {
+ this.type = type;
+ } else {
+ System.out.println("Invalid port type");
+ }
}
public IPAddress getIpAddress() {
@@ -18,7 +57,20 @@ public IPAddress getIpAddress() {
}
public void setIpAddress(IPAddress ipAddress) {
- this.ipAddress = ipAddress;
+ if (ipAddress == null) {
+ System.out.println("IP Address entered is empty");
+ } else if (ipAddress.equals(this.ipAddress)) {
+ System.out.println("IP Address is the same");
+ } else if (subNetMask != null && nicManager.ipAndSubnetExists(ipAddress, subNetMask)) {
+ System.err.println("setIpAddress() method called");
+ // Check if the combination of ip address and subnet mask is already set up for another NIC
+ System.err.println("This combination of IP Address and Subnet Mask already exists");
+ // Reset the subnet mask also
+ this.subNetMask = null;
+ } else {
+ System.out.println("IP Address set to: " + ipAddress);
+ this.ipAddress = ipAddress;
+ }
}
public MACAddress getMacAddress() {
@@ -30,13 +82,24 @@ public SubnetMask getSubnetMask() {
}
public void setSubnetMask(SubnetMask subnetMask) {
- this.subNetMask = subnetMask;
+ if (subnetMask == null) {
+ System.out.println("Subnet Mask entered is empty");
+ } else if (subnetMask.equals(this.subNetMask)) {
+ System.out.println("Subnet Mask already set");
+ } else if (ipAddress != null && nicManager.ipAndSubnetExists(ipAddress, subnetMask)) {
+ System.err.println("setSubnetMask() method called");
+ System.err.println("This combination of IP Address and Subnet Mask already exists");
+ // Reset the ip address also.
+ this.ipAddress = null;
+ } else {
+ this.subNetMask = subnetMask;
+ }
}
public IPAddress getNetwork() {
IPAddress network = new IPAddress();
- // AND the IP address bits with the subnet mask bits and it should return the network bits for each byte.
+ // AND the IP address bits with the subnet mask bits, and it should return the network bits for each byte.
byte byte3 = (byte) (this.ipAddress.getIpAddress()[3] & this.subNetMask.getSubnetMask()[3]);
byte byte2 = (byte) (this.ipAddress.getIpAddress()[2] & this.subNetMask.getSubnetMask()[2]);
byte byte1 = (byte) (this.ipAddress.getIpAddress()[1] & this.subNetMask.getSubnetMask()[1]);
@@ -50,4 +113,49 @@ public IPAddress getNetwork() {
return network;
}
+
+ /**
+ * Sets up a connection to another NIC.
+ * @param otherNIC This is the other NIC that this instance will connect to.
+ */
+ public void setConnection(NIC otherNIC) {
+ this.connection = otherNIC;
+ }
+
+ /**
+ * Checks whether this NIC is connected to another NIC.
+ * @return True if there is a connection, false if not.
+ */
+ public boolean isConnected() {
+ return this.connection != null;
+ }
+
+ public NIC getConnectedNIC() {
+ return this.connection;
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public void setPriority(int priority) {
+ this.priority = priority;
+ }
+
+ public String getDeadTime() {
+ return this.deadTime;
+ }
+
+ public void setDeadTime(String deadTime) {
+ this.deadTime = deadTime;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public Device getAssignedDevice() {
+ return assignedDevice;
+ }
+
}
\ No newline at end of file
diff --git a/src/NICManager.java b/src/NICManager.java
new file mode 100644
index 0000000..e1e3327
--- /dev/null
+++ b/src/NICManager.java
@@ -0,0 +1,83 @@
+import java.util.ArrayList;
+
+public class NICManager {
+ // Holds the all the NICs that have been created.
+ private ArrayList createdNICs = new ArrayList<>();
+ // This will hold the instance of the class, it is used to ensure that this will be the only instance that can be used.
+ // static variable to indicate the value is associated with the class, and not the object, this ensures that the same
+ // instance is held throughout the class. new NICManager() calls the private constructor, which can only be accessed
+ // from within itself.
+ private static NICManager instance = new NICManager();
+
+ /**
+ * Private constructor, so no other class can call the constructor, thus not allowing any more instances of the class.
+ */
+ private NICManager() {
+
+ }
+
+ /**
+ * Method for returning the instance of the object, since only one instance can exist.
+ * @return NICManager instance
+ */
+ public static NICManager getInstance() {
+ return instance;
+ }
+
+ /**
+ * Inserts a NIC within the ArrayList
+ * @param nic The NIC to be inserted.
+ */
+ public void addNIC(NIC nic) {
+ createdNICs.add(nic);
+ }
+
+ /**
+ * Checks if a MACAddress has already been created for another NIC.
+ * @param macAddress MACAddress that will be searched for.
+ * @return If a MACAddress exists returns true, else false.
+ */
+ public boolean macExists(MACAddress macAddress) {
+ for (NIC nic : createdNICs) {
+ if (nic.getMacAddress().equals(macAddress)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Checks if a IPAddress and SubnetMask combination are being used by another NIC.
+ * @param ipAddress Used for checking for a matching IPAddress.
+ * @param subnetMask Used for checking a matching SubnetMask.
+ * @return If both the ipAddress and subnetMask match, then return true, else false.
+ */
+ public boolean ipAndSubnetExists(IPAddress ipAddress, SubnetMask subnetMask) {
+ for (NIC nic : createdNICs) {
+ // Check if the IP Address or the Subnet Mask is not equal to null, if so go to the next iteration
+ if (nic.getIpAddress() == null || nic.getSubnetMask() == null) {
+ continue;
+ }
+ // If the ipAddress and the subnetMask match with the subnetMask and ipAddress of the NIC, then return true.
+ if (nic.getIpAddress().equals(ipAddress) && nic.getSubnetMask().equals(subnetMask)) {
+ return true;
+ }
+ }
+ // When no matches are mad then return false.
+ return false;
+ }
+
+ public Device getDevice(IPAddress ipAddress, SubnetMask subnetMask) {
+ for (NIC nic : createdNICs) {
+ if (nic.getIpAddress() == null || nic.getSubnetMask() == null) {
+ continue;
+ }
+ if (nic.getIpAddress().equals(ipAddress) && nic.getSubnetMask().equals(subnetMask)) {
+ return nic.getAssignedDevice();
+ }
+ }
+
+ System.out.println("No device found for IP " + ipAddress + " and subnet " + subnetMask);
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/src/OSPFNeighboursScrollPane.java b/src/OSPFNeighboursScrollPane.java
new file mode 100644
index 0000000..1d096ca
--- /dev/null
+++ b/src/OSPFNeighboursScrollPane.java
@@ -0,0 +1,58 @@
+import javax.swing.*;
+
+public class OSPFNeighboursScrollPane extends JScrollPane {
+ JTable table;
+ String[] columnNames = { "Neighbour ID", "Pri", "State", "Dead Time", "Address", "Interface" };
+ Router router;
+
+ public OSPFNeighboursScrollPane(Router router) {
+ this.router = router;
+ this.table = new JTable(getRows(), this.columnNames);
+ super.setViewportView(table);
+ setColumnWidth();
+ }
+
+ private int getConnectionCount() {
+ int count = 0;
+ for (NIC nic : router.getNICList()) {
+ if (nic.isConnected()) {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ private String[][] getRows() {
+ String[][] rows = new String[getConnectionCount()][columnNames.length];
+ for (int i = 0; i < getConnectionCount(); i++) {
+ NIC currentNic = router.getNICList().get(i).getConnectedNIC();
+ // TODO:
+ // Neighbour ID
+ rows[i][0] = router.getRid();
+ // Pri
+ rows[i][1] = Integer.toString(currentNic.getPriority());
+ // State
+ rows[i][2] = currentNic.getState();
+ // Dead time
+ rows[i][3] = currentNic.getDeadTime();
+ // Address
+ if (currentNic.getIpAddress() != null) {
+ rows[i][4] = currentNic.getIpAddress().toString();
+ }
+ // Interface
+ rows[i][5] = currentNic.getType();
+ }
+ return rows;
+ }
+
+ private void setColumnWidth() {
+ // Neighbor ID
+ table.getColumnModel().getColumn(0).setPreferredWidth(15);
+ // Pri
+ table.getColumnModel().getColumn(1).setPreferredWidth(2);
+ // State
+ table.getColumnModel().getColumn(2).setPreferredWidth(2);
+ // Dead Time
+ table.getColumnModel().getColumn(3).setPreferredWidth(5);
+ }
+}
\ No newline at end of file
diff --git a/src/OctetArray.java b/src/OctetArray.java
index 0ed9c38..d35de48 100644
--- a/src/OctetArray.java
+++ b/src/OctetArray.java
@@ -1,21 +1,43 @@
public abstract class OctetArray {
private byte[] octetArray;
- private int octetArraySize;
+ private String separator;
- public OctetArray(int octetArraySize) {
- this.octetArraySize = octetArraySize;
+ public OctetArray(String separator, int size) {
+ this.octetArray = new byte[size];
+ this.separator = separator;
}
- public byte[] getOctetArray() { return octetArray; }
+ public byte[] getOctetArray() {
+ return octetArray;
+ }
public String toString() {
- String[] byteString = new String[octetArraySize];
- for (int i = 0; i < octetArraySize; i++) {
- byteString[i] = Integer.toString(Byte.toUnsignedInt(octetArray[i]));
+ String bytesString = "";
+ for (int i = 0; i < octetArray.length; i++) {
+ if (!(i == octetArray.length - 1)) {
+ bytesString = bytesString + Integer.toString(Byte.toUnsignedInt(octetArray[i])) + separator;
+ } else {
+ // Octet at the very right doesn't need the separator.
+ bytesString = bytesString + Integer.toString(Byte.toUnsignedInt(octetArray[i]));
+ }
}
+ return bytesString;
+ }
+
+ // TODO: Start here next
+ public void setOctetArray(String octetArray) {
+
+ }
- System.out.println(String.join(".", byteString));
+ public void setSpecificByte(int byteLocation, byte byteVal) {
+
+ }
+
+ public boolean equals(Object object) {
+ return true;
+ }
- return String.join(".", byteString);
+ public byte[] octetArrayStringToByteArray(String octetArray) {
+ return null;
}
}
diff --git a/src/OctetArrayTest.java b/src/OctetArrayTest.java
deleted file mode 100644
index 4817534..0000000
--- a/src/OctetArrayTest.java
+++ /dev/null
@@ -1,5 +0,0 @@
-import static org.junit.jupiter.api.Assertions.*;
-
-class OctetArrayTest {
-
-}
\ No newline at end of file
diff --git a/src/PC.java b/src/PC.java
index 701858e..b94183a 100644
--- a/src/PC.java
+++ b/src/PC.java
@@ -11,7 +11,7 @@ public class PC extends Device {
super(name);
// Set up the NIC for the PC, which only has the FastEthernet 0/0
- NIC fa00 = new NIC("FastEthernet 0/0");
+ NIC fa00 = new NIC("FastEthernet 0/0", this);
fa00.setIpAddress(ipaddress);
fa00.setSubnetMask(subnetMask);
// Add the fa00 NIC to the ArrayList of nicList.
@@ -19,6 +19,17 @@ public class PC extends Device {
super.setNICList(new ArrayList<>(List.of(fa00)));
}
+ /**
+ * Overloaded constructor with only the name as a parameter.
+ * @param name The name for the PC.
+ */
+ PC(String name) {
+ super(name);
+
+ NIC fa00 = new NIC("FastEthernet 0/0", this);
+ super.setNICList(new ArrayList<>(List.of(fa00)));
+ }
+
public NIC getPortFA00() { return super.getNICList().get(0); }
// You shouldn't be able to change the name of the interface, as they are always predefined. Only the IP can be
@@ -35,4 +46,12 @@ public void setDefaultGateway(IPAddress ipaddress, SubnetMask subnetMask) {
this.defaultGatewayIPAddress = ipaddress;
this.defaultGatewaySubnetMask = subnetMask;
}
+
+ public void setPortFA00IPAddress(IPAddress ipAddress) {
+ super.getNICList().get(0).setIpAddress(ipAddress);
+ }
+
+ public void setPortFA00SubnetMask(SubnetMask subnetMask) {
+ super.getNICList().get(0).setSubnetMask(subnetMask);
+ }
}
\ No newline at end of file
diff --git a/src/PCButton.java b/src/PCButton.java
new file mode 100644
index 0000000..900f0c3
--- /dev/null
+++ b/src/PCButton.java
@@ -0,0 +1,72 @@
+import javax.swing.*;
+import java.awt.*;
+
+public class PCButton extends JButton {
+ private PC pc;
+ private PreconfiguredNetworkPanel networkPanel;
+
+ public PCButton(String name, PreconfiguredNetworkPanel networkPanel) {
+ super();
+ this.pc = new PC(name);
+ this.networkPanel = networkPanel;
+
+ // Set the pc icon
+ ImageIcon icon = new ImageIcon("images/icons8-pc-50.png");
+ Image scaledImage = icon.getImage().getScaledInstance(50, 50, Image.SCALE_SMOOTH);
+ setIcon(new ImageIcon(scaledImage));
+
+ // Remove the border around the button.
+ setBorderPainted(false);
+ // Match the same colour as the background.
+ setBackground(new Color(240, 240, 240));
+
+ // Set tooltip to show the pc name
+ setToolTipText(name);
+
+ super.addActionListener(e -> {
+ String[] labels = {
+ "Name",
+ "Fa 0/0 IP Address",
+ "Fa 0/0 Subnet Mask"
+ };
+
+ String[] fields = {
+ pc.getName(),
+ pc.getPortFA00().getIpAddress() == null ? "" : pc.getPortFA00().getIpAddress().toString(),
+ pc.getPortFA00().getSubnetMask() == null ? "" : pc.getPortFA00().getSubnetMask().toString(),
+ };
+
+ PCInfoFrame pcInfoFrame = new PCInfoFrame(
+ pc.getName(),
+ labels,
+ fields,
+ pc,
+ this,
+ networkPanel
+ );
+
+ pcInfoFrame.setEditable("Fa 0/0 MAC Address", false);
+
+ pcInfoFrame.setVisible(true);
+ });
+ }
+
+ public PC getPC() {
+ return pc;
+ }
+
+ public JFrame getInfoFrame() {
+ JFrame frame = new JFrame();
+
+ frame.setSize( 600, 400);
+ frame.setTitle(pc.getName());
+ frame.setLocationRelativeTo(null);
+ // DISPOSE_ON_CLOSE will ensure that the windows won't all close.
+ frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+
+ JPanel pcInfoPanel = new JPanel();
+ pcInfoPanel.setLayout(new GridLayout(0, 2));
+
+ return frame;
+ }
+}
diff --git a/src/PCInfoFrame.java b/src/PCInfoFrame.java
new file mode 100644
index 0000000..b094e29
--- /dev/null
+++ b/src/PCInfoFrame.java
@@ -0,0 +1,121 @@
+import java.awt.*;
+import java.util.ArrayList;
+import javax.swing.*;
+
+public class PCInfoFrame extends JFrame {
+
+ private ArrayList infoFields = new ArrayList<>();
+ private JButton saveButton = new JButton("Save");
+ private JButton pingButton = new JButton("Ping another PC");
+ private PreconfiguredNetworkPanel networkPanel;
+
+ public PCInfoFrame(
+ String title,
+ String[] labels,
+ String[] fields,
+ PC pc,
+ PCButton pcButton,
+ PreconfiguredNetworkPanel networkPanel
+ ) {
+ if (labels.length != fields.length) {
+ throw new IllegalArgumentException(
+ "Number of labels and fields do not match"
+ );
+ }
+
+ this.networkPanel = networkPanel;
+
+ super.setTitle(title);
+ super.setSize(300, 300);
+ super.setLocationRelativeTo(null); // Make it center.
+ super.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // DISPOSE_ON_CLOSE Make sure the whole app doesn't shut down.
+ super.setResizable(false);
+
+ JTabbedPane tabs = new JTabbedPane();
+ JPanel generalInformationPanel = new JPanel();
+ generalInformationPanel.setLayout(new GridLayout(0, 1));
+
+ for (int i = 0; i < labels.length; i++) {
+ infoFields.add(new InfoField(labels[i], fields[i]));
+ // Add the JLabel and JTextField to the JFrame.
+ generalInformationPanel.add(infoFields.get(i));
+ }
+ tabs.addTab("General", generalInformationPanel);
+ super.add(tabs);
+
+ this.saveButton.addActionListener(e -> {
+ System.out.println("Saving");
+ pc.setName(infoFields.get(0).getTextField().getText());
+ pcButton.setText(infoFields.get(0).getTextField().getText());
+ this.setTitle(infoFields.get(0).getTextField().getText());
+ try {
+ IPAddress ipFa00 = new IPAddress(
+ infoFields.get(1).getTextField().getText()
+ );
+ pc.setPortFA00IPAddress(ipFa00);
+ } catch (IllegalArgumentException exception) {
+ System.out.println("Invalid IP address for Fa 0/0");
+ }
+ try {
+ SubnetMask subnetFa00 = new SubnetMask(
+ infoFields.get(2).getTextField().getText()
+ );
+ pc.setPortFA00SubnetMask(subnetFa00);
+ } catch (IllegalArgumentException exception) {
+ System.out.println("Invalid Subnet mask for Fa 0/0");
+ }
+ });
+ generalInformationPanel.add(saveButton);
+
+ this.pingButton.addActionListener(e1 -> {
+ System.out.println("Pinging");
+
+ JFrame destinationQuery = new JFrame();
+ destinationQuery.setSize(400, 200);
+ destinationQuery.setLocationRelativeTo(null);
+ destinationQuery.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ destinationQuery.setResizable(false);
+ destinationQuery.setVisible(true);
+ destinationQuery.setLayout(new GridLayout(0, 1));
+
+ InfoField infoDestinationIPAddress = new InfoField("Destination IP Address", "");
+ destinationQuery.add(infoDestinationIPAddress);
+
+ InfoField infoDestinationSubnetMask = new InfoField("Destination Subnet Mask", "");
+ destinationQuery.add(infoDestinationSubnetMask);
+
+ JButton startPingButton = new JButton("Start ping");
+ startPingButton.addActionListener(e2 -> {
+ String strDestinationIP = infoDestinationIPAddress.getTextField().getText();
+ String strDestinationSubnetMask = infoDestinationSubnetMask.getTextField().getText();
+ PrePingProtocol prePingProtocol = new PrePingProtocol(pc, strDestinationIP, strDestinationSubnetMask, networkPanel);
+ prePingProtocol.ping();
+ });
+ destinationQuery.add(startPingButton);
+
+ });
+ generalInformationPanel.add(pingButton);
+ }
+
+ public void setEditable(String fieldLabel, boolean editable) {
+ for (InfoField infoField : infoFields) {
+ if (infoField.getLabel().getText().equals(fieldLabel)) {
+ infoField.setEditable(editable);
+ }
+ }
+ }
+
+ private boolean destinationExists(String destinationIPAddress, String destinationSubnetMask) {
+ // Convert the destination subnet mask string to a SubnetMask object
+ SubnetMask destSubnetMask = new SubnetMask(destinationSubnetMask);
+
+ // Convert the destination IP address string to an IPAddress object
+ IPAddress destIPAddress = new IPAddress(destinationIPAddress);
+
+ // Get the NICManager instance which keeps track of all NICs in the network
+ NICManager nicManager = NICManager.getInstance();
+
+ // Check if the IP and subnet mask combination exists in any NIC in the network
+ return nicManager.ipAndSubnetExists(destIPAddress, destSubnetMask);
+ }
+}
diff --git a/src/PacketAnimation.java b/src/PacketAnimation.java
new file mode 100644
index 0000000..dcfe74c
--- /dev/null
+++ b/src/PacketAnimation.java
@@ -0,0 +1,117 @@
+import javax.swing.*;
+import java.awt.*;
+import java.util.List;
+
+public class PacketAnimation extends JPanel {
+ private List pointList; // List of ponts to do the animation
+ private int currentPoint = 0; // Current point in the animation
+ private boolean animating = false; // Used for checking if the animation is still going
+ private Image letterImage; // Used for the packet image
+
+ private int currentX, currentY; // Current position of the image
+ private int endX, endY; // Target position
+
+ private static final int TIMER_DELAY = 20; // ms
+ private static final int SPEED = 4; // pixels per frame
+
+ public PacketAnimation(List pointList) {
+ this.pointList = pointList;
+
+ // Load the letter icon
+ ImageIcon icon = new ImageIcon("images/icons8-letter-50.png");
+ letterImage = icon.getImage().getScaledInstance(40, 40, Image.SCALE_SMOOTH);
+
+ // A timer is created, that has a delay set by the TIMER_DELAY, which is the amoutn of time.
+ // Then it calls the updatePosition() method, which then moves the packet to the next increment
+ // of x and y.
+ Timer timer = new Timer(TIMER_DELAY, e -> updatePosition());
+ timer.start();
+ }
+
+ public void startAnimation() {
+ // If there are less than 2 points, then there cannot be an animation
+ if (pointList.size() < 2) return;
+
+ currentPoint = 0;
+ animating = true;
+ currentX = pointList.get(0).x;
+ currentY = pointList.get(0).y;
+ endX = pointList.get(1).x;
+ endY = pointList.get(1).y;
+ }
+
+ private void updatePosition() {
+ if (!animating) return;
+
+ // Calculate the difference between the target coordinates and the current position
+ int dx = endX - currentX;
+ int dy = endY - currentY;
+ // Use Pythagorean theorem to get the point from the start to the end.
+ // This is done to get the straight point from the starting point, to the ending point. This
+ // is needed because of the angles that are used when making connections.
+ double distance = Math.sqrt(dx * dx + dy * dy);
+
+ // If the distance of the packet is really close, then just start moving to the next point.
+ // This is done because sometimes it would get stuck, as it never reached the point exactly.
+ if (distance <= 5) {
+ // Move to next point
+ currentPoint++;
+ // Out of bounds check
+ if (currentPoint + 1 < pointList.size()) {
+ // Move to the next end point.
+ endX = pointList.get(currentPoint + 1).x;
+ endY = pointList.get(currentPoint + 1).y;
+ } else {
+ // If all points finished, then animation is finished.
+ animating = false;
+ }
+ } else {
+ // Move in direction of the current end point
+ // The stepX and stepY is used to determine how much each axis contributes to the overall movement.
+ // This all depends on the angle at which it moves. It is basically checking the rate of change of y,
+ // and the rate of change of x. These are then added to the currentX and currentY, which moves it
+ // by the required rate of change.
+ // The SPEED is then used to also calculate how much the actual change should take place, which is used
+ // to just make th animation faster or slower.
+ double stepX = SPEED * dx / distance;
+ double stepY = SPEED * dy / distance;
+ currentX += (int) stepX;
+ currentY += (int) stepY;
+ }
+
+ repaint(); // Redraw at new position
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ // Clears the panel, and applies the background colour
+ // This is needed to repaint the packet
+ super.paintComponent(g);
+
+ if (animating) {
+ // If it is still animating, then it will draw the image of the packet, at the positions
+ g.drawImage(letterImage, currentX, currentY, null);
+ }
+ }
+
+ // Testing
+ public static void main(String[] args) {
+ List corners = List.of(
+ new Point(100, 100),
+ new Point(500, 100),
+ new Point(500, 500),
+ new Point(100, 500),
+ new Point(300, 300),
+ new Point(300, 100)
+ );
+
+ JFrame frame = new JFrame();
+ PacketAnimation panel = new PacketAnimation(corners);
+ frame.add(panel);
+ frame.setSize(600, 600);
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setVisible(true);
+
+ SwingUtilities.invokeLater(panel::startAnimation);
+ }
+}
diff --git a/src/PingProtocol.java b/src/PingProtocol.java
index 80e1da9..e0ca41e 100644
--- a/src/PingProtocol.java
+++ b/src/PingProtocol.java
@@ -87,7 +87,7 @@ private void delay(int seconds) {
private void displayNICList(ArrayList nicList) {
for (int i = 0; i < nicList.size(); i++) {
- System.out.println(i + 1 + " " + nicList.get(i).getName());
+ System.out.println(i + 1 + " " + nicList.get(i).getType());
}
}
@@ -108,7 +108,7 @@ private void arpProcessSuccessful(Device sourceDevice, Device destinationDevice)
"-", // Placeholder for now, not really needed in my protocol, just in case for future.
destinationNIC.getMacAddress(),
"ARPA", // Placeholder for now, not really needed in my protocol, just in case for future.
- destinationNIC.getName());
+ destinationNIC.getType());
// Adding to the destination Device ARP table, with the necessary details.
destinationDevice.getARPTable().addEntry(
"Internet", // Placeholder for now, not really needed in my protocol, just in case for future.
@@ -116,7 +116,7 @@ private void arpProcessSuccessful(Device sourceDevice, Device destinationDevice)
"-", // Placeholder for now, not really needed in my protocol, just in case for future.
sourceNIC.getMacAddress(),
"ARPA", // Placeholder for now, not really needed in my protocol, just in case for future.
- sourceNIC.getName());
+ sourceNIC.getType());
System.out.println("--------- " + sourceDevice.getName() + " ARP Table ---------");
System.out.println(sourceDevice.getARPTable());
diff --git a/src/PrePathCalculation.java b/src/PrePathCalculation.java
new file mode 100644
index 0000000..d4037c7
--- /dev/null
+++ b/src/PrePathCalculation.java
@@ -0,0 +1,178 @@
+public class PrePathCalculation {
+ private Router[] routers = new Router[7];
+
+ public PrePathCalculation(Router[] routers) {
+ if (routers.length != 7) {
+ throw new IllegalArgumentException("Router array length should be equal to 7");
+ } else {
+ this.routers = routers;
+ }
+ }
+
+ public String getShortestPath(String startPc, String endPc) {
+ // PC0, PC1
+ if ((startPc.equals("PC0") && endPc.equals("PC1")) || (startPc.equals("PC1") && endPc.equals("PC0"))) {
+ int paths[] = { getPc0Pc1PathCost0(), getPc0Pc1PathCost1(), getPc0Pc1PathCost2(), getPc0Pc1PathCost3() };
+ switch (findShortestPathIndex(paths)) {
+ case 0:
+ return "PC0--R0--R1--R2--R3--PC1";
+ case 1:
+ return "PC0--R0--R1--R4--R2--R3--PC1";
+ case 2:
+ return "PC0--R0--R5--R6--R4--R2--R3--PC1";
+ case 3:
+ return "PC0--R0--R5--R6--R4--R1--R2--R3--PC1";
+ default:
+ System.err.println("Invalid path comparison for " + startPc + " and " + endPc);
+ return "No path";
+ }
+ } else if ((startPc.equals("PC0") && endPc.equals("PC2")) || (startPc.equals("PC2") && endPc.equals("PC0"))) {
+ int paths[] = { getPc0Pc2PathCost0(), getPc0Pc2PathCost1(), getPc0Pc2PathCost2() };
+ switch (findShortestPathIndex(paths)) {
+ case 0:
+ return "PC0--R0--R5--R6--PC2";
+ case 1:
+ return "PC0--R0--R1--R4--R6--PC2";
+ case 2:
+ return "PC0--R0--R1--R2--R4--R6--PC2";
+ default:
+ System.err.println("Invalid path comparison for " + startPc + " and " + endPc);
+ return "No path";
+ }
+ } else if ((startPc.equals("PC1") && endPc.equals("PC2")) || (startPc.equals("PC2") && endPc.equals("PC1"))) {
+ int paths[] = { getPc1Pc2PathCost0(), getPc1Pc2PathCost1(), getPc1Pc2PathCost2() };
+ switch (findShortestPathIndex(paths)) {
+ case 0:
+ return "PC1--R3--R2--R4--R6--PC2";
+ case 1:
+ return "PC1--R3--R2--R1--R4--R6--PC2";
+ case 2:
+ return "PC1--R3--R2--R1--R0--R5--R6--PC2";
+ default:
+ System.err.println("Invalid path comparison for " + startPc + " and " + endPc);
+ return "No path";
+ }
+ }
+ System.err.println("No path found between " + startPc + " and " + endPc);
+ return "No path";
+ }
+
+ private int findShortestPathIndex(int paths[]) {
+ int shortestIndex = 0;
+ int shortestCost = paths[0];
+
+ for (int i = 1; i < paths.length; i++) {
+ if (paths[i] < shortestCost) {
+ shortestCost = paths[i];
+ shortestIndex = i;
+ }
+ }
+
+ return shortestIndex;
+ }
+
+ // PC0 PC2 path
+ // 1. R0--R5--R6
+ private int getPc0Pc2PathCost0() {
+ return getR0R5Cost() + getR5R6Cost();
+ }
+
+ // 2. R0--R1--R4--R6
+ private int getPc0Pc2PathCost1() {
+ return getR0R1Cost() + getR1R4Cost() + getR4R6Cost();
+ }
+
+ // 3. R0--R1--R2--R4--R6
+ private int getPc0Pc2PathCost2() {
+ return getR0R1Cost() + getR1R2Cost() + getR2R4Cost() + getR4R6Cost();
+ }
+
+ // PC0 PC1 path
+ // 1. R0--R1--R2--R3
+ private int getPc0Pc1PathCost0() {
+ return getR0R1Cost() + getR1R2Cost() + getR2R3Cost();
+ }
+
+ // 2. R0--R1--R4--R2--R3
+ private int getPc0Pc1PathCost1() {
+ return getR0R1Cost() + getR1R4Cost() + getR2R4Cost() + getR2R3Cost();
+ }
+
+ // 3. R0--R5--R6--R4--R2--R3
+ private int getPc0Pc1PathCost2() {
+ return getR0R5Cost() + getR5R6Cost() + getR4R6Cost() + getR2R4Cost() + getR2R3Cost();
+ }
+
+ // 4. R0--R5--R6--R4--R1--R2--R3
+ private int getPc0Pc1PathCost3() {
+ return getR0R5Cost() + getR5R6Cost() + getR4R6Cost() + getR1R4Cost() + getR1R2Cost() + getR2R3Cost();
+ }
+
+ // PC1 PC2 path
+ // 1. R3--R2--R4--R6
+ private int getPc1Pc2PathCost0() {
+ return getR2R3Cost() + getR2R4Cost() + getR4R6Cost();
+ }
+
+ // 2. PC1 || R3--R2--R1--R4--R6 || PC2
+ private int getPc1Pc2PathCost1() {
+ return getR2R3Cost() + getR1R2Cost() + getR1R4Cost() + getR4R6Cost();
+ }
+
+ // 3. PC1 || R3--R2--R1--R0--R5--R6 || PC2
+ private int getPc1Pc2PathCost2() {
+ return getR2R3Cost() + getR1R2Cost() + getR0R1Cost() + getR0R5Cost() + getR5R6Cost();
+ }
+
+ private int getPortCost(String name) {
+ // TODO: Temporary, need to change so it will only be Fastethernet
+ if (name.equals("Fastethernet 0/0") || name.equals("Fastethernet 0/1") || name.equals("Fastethernet 0/2") || name.equals("FastEthernet")) {
+ return 10;
+ } else {
+ return 1;
+ }
+ }
+
+ private int getSectionCost(Router firstRouter, int firstRouterPort, Router secondRouter, int secondRouterPort) {
+ String firstRouterPortName = firstRouter.getNICList().get(firstRouterPort).getType();
+ String secondRouterPortName = secondRouter.getNICList().get(secondRouterPort).getType();
+
+ if (getPortCost(firstRouterPortName) == 10 || getPortCost(secondRouterPortName) == 10) {
+ return 10;
+ } else {
+ return 1;
+ }
+ }
+
+ public int getR0R5Cost() {
+ return getSectionCost(routers[0], 2, routers[5], 0);
+ }
+
+ public int getR0R1Cost() {
+ return getSectionCost(routers[0], 1, routers[1], 0);
+ }
+
+ public int getR5R6Cost() {
+ return getSectionCost(routers[5], 1, routers[6], 0);
+ }
+
+ public int getR4R6Cost() {
+ return getSectionCost(routers[4], 2, routers[6], 1);
+ }
+
+ public int getR1R4Cost() {
+ return getSectionCost(routers[1], 2, routers[4], 0);
+ }
+
+ public int getR1R2Cost() {
+ return getSectionCost(routers[1], 1, routers[2], 0);
+ }
+
+ public int getR2R4Cost() {
+ return getSectionCost(routers[2], 2, routers[4], 1);
+ }
+
+ public int getR2R3Cost() {
+ return getSectionCost(routers[2], 1, routers[3], 0);
+ }
+}
\ No newline at end of file
diff --git a/src/PrePingProtocol.java b/src/PrePingProtocol.java
new file mode 100644
index 0000000..a3e551c
--- /dev/null
+++ b/src/PrePingProtocol.java
@@ -0,0 +1,221 @@
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Stream;
+
+public class PrePingProtocol {
+ private Device sourceDevice;
+ private Device destinationDevice;
+ private Router[] routers;
+ private PC[] pcs;
+ private boolean canPing;
+ private PrePathCalculation prePathCalculation;
+ private PreconfiguredNetworkPanel networkPanel;
+
+ // Declare coordinates as fields but don't initialize yet
+ private Point PC0_COORDINATES;
+ private Point PC1_COORDINATES;
+ private Point PC2_COORDINATES;
+ private Point R0_COORDINATES;
+ private Point R1_COORDINATES;
+ private Point R2_COORDINATES;
+ private Point R3_COORDINATES;
+ private Point R4_COORDINATES;
+ private Point R5_COORDINATES;
+ private Point R6_COORDINATES;
+
+ public PrePingProtocol(Device sourceDevice, String strDestinationIP, String strDestinationSubnet, PreconfiguredNetworkPanel networkPanel) {
+ this.sourceDevice = sourceDevice;
+ this.networkPanel = networkPanel;
+ this.routers = networkPanel.getRouters();
+ this.pcs = networkPanel.getPCs();
+
+ // Initialize coordinates after networkPanel is set
+ this.PC0_COORDINATES = networkPanel.getDeviceCoordinates("PC0");
+ this.PC1_COORDINATES = networkPanel.getDeviceCoordinates("PC1");
+ this.PC2_COORDINATES = networkPanel.getDeviceCoordinates("PC2");
+ this.R0_COORDINATES = networkPanel.getDeviceCoordinates("R0");
+ this.R1_COORDINATES = networkPanel.getDeviceCoordinates("R1");
+ this.R2_COORDINATES = networkPanel.getDeviceCoordinates("R2");
+ this.R3_COORDINATES = networkPanel.getDeviceCoordinates("R3");
+ this.R4_COORDINATES = networkPanel.getDeviceCoordinates("R4");
+ this.R5_COORDINATES = networkPanel.getDeviceCoordinates("R5");
+ this.R6_COORDINATES = networkPanel.getDeviceCoordinates("R6");
+
+ if (!destinationExists(new IPAddress(strDestinationIP), new SubnetMask(strDestinationSubnet))) {
+ canPing = false;
+ System.out.println("Destination does not exist");
+ // Show error popup if destination doesn't exist
+ javax.swing.JOptionPane.showMessageDialog(
+ null,
+ String.format("""
+ IP Address: %s\n
+ SubnetMask: %s\n
+ Destination does not exist in the network""", strDestinationIP, strDestinationSubnet),
+ "Destination Not Found",
+ javax.swing.JOptionPane.ERROR_MESSAGE
+ );
+ } else {
+ canPing = true;
+ this.destinationDevice = NICManager.getInstance().getDevice(new IPAddress(strDestinationIP), new SubnetMask(strDestinationSubnet));
+ this.prePathCalculation = new PrePathCalculation(this.routers);
+ }
+ }
+
+ public void ping() {
+ if (canPing) {
+ String sourceDeviceName = sourceDevice.getName();
+ String destinationDeviceName = destinationDevice.getName();
+ String path = prePathCalculation.getShortestPath(sourceDeviceName, destinationDeviceName);
+ System.out.println(sourceDeviceName + " -> " + destinationDeviceName);
+ pathAnimation(path, sourceDeviceName);
+ }
+ }
+
+ private boolean destinationExists(IPAddress ipAddress, SubnetMask subnetMask) {
+ // Get the NICManager instance which keeps track of all NICs in the network
+ NICManager nicManager = NICManager.getInstance();
+
+ // Check if the IP and subnet mask combination exists in any NIC in the network
+ return nicManager.ipAndSubnetExists(ipAddress, subnetMask);
+ }
+
+ private void pathAnimation(String path, String startingPoint) {
+ System.out.println(path);
+ PacketAnimation anim;
+ List pointList;
+ List part1;
+ List part2;
+
+ // NOTE: Tried to use a for loop for these, but the animations just get canceled
+ // once the next one starts.
+ switch (path) {
+ // PC0 to PC1 paths
+ case "PC0--R0--R1--R2--R3--PC1":
+ part1 = List.of(PC0_COORDINATES, R0_COORDINATES, R1_COORDINATES, R2_COORDINATES, R3_COORDINATES, PC1_COORDINATES);
+ //part2 = part1.reversed();
+ part2 = List.of(PC1_COORDINATES, R3_COORDINATES, R2_COORDINATES, R1_COORDINATES, R0_COORDINATES, PC0_COORDINATES);
+ if (startingPoint.equals("PC0")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ //pointList = Stream.concat(pointList.stream(), pointList.stream()).toList();
+ break;
+
+ case "PC0--R0--R1--R4--R2--R3--PC1":
+ part1 = List.of(PC0_COORDINATES, R0_COORDINATES, R1_COORDINATES, R4_COORDINATES, R2_COORDINATES, R3_COORDINATES, PC1_COORDINATES);
+ part2 = List.of(PC1_COORDINATES, R3_COORDINATES, R2_COORDINATES, R4_COORDINATES, R1_COORDINATES, R0_COORDINATES, PC0_COORDINATES);
+ if (startingPoint.equals("PC0")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ break;
+
+ case "PC0--R0--R5--R6--R4--R2--R3--PC1":
+ part1 = List.of(PC0_COORDINATES, R0_COORDINATES, R5_COORDINATES, R6_COORDINATES, R4_COORDINATES, R2_COORDINATES, R3_COORDINATES, PC1_COORDINATES);
+ part2 = List.of(PC1_COORDINATES, R3_COORDINATES, R2_COORDINATES, R4_COORDINATES, R6_COORDINATES, R5_COORDINATES, R0_COORDINATES, PC0_COORDINATES);
+ if (startingPoint.equals("PC0")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ break;
+
+ case "PC0--R0--R5--R6--R4--R1--R2--R3--PC1":
+ part1 = List.of(PC0_COORDINATES, R0_COORDINATES, R5_COORDINATES, R6_COORDINATES, R4_COORDINATES, R1_COORDINATES, R2_COORDINATES, R3_COORDINATES, PC1_COORDINATES);
+ part2 = List.of(PC1_COORDINATES, R3_COORDINATES, R2_COORDINATES, R1_COORDINATES, R4_COORDINATES, R6_COORDINATES, R5_COORDINATES, R0_COORDINATES, PC0_COORDINATES);
+ if (startingPoint.equals("PC0")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ break;
+
+ // PC0 to PC2 paths
+ case "PC0--R0--R5--R6--PC2":
+ part1 = List.of(PC0_COORDINATES, R0_COORDINATES, R5_COORDINATES, R6_COORDINATES, PC2_COORDINATES);
+ part2 = List.of(PC2_COORDINATES, R6_COORDINATES, R5_COORDINATES, R0_COORDINATES, PC0_COORDINATES);
+ if (startingPoint.equals("PC0")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ break;
+
+ case "PC0--R0--R1--R4--R6--PC2":
+ part1 = List.of(PC0_COORDINATES, R0_COORDINATES, R1_COORDINATES, R4_COORDINATES, R6_COORDINATES, PC2_COORDINATES);
+ part2 = List.of(PC2_COORDINATES, R6_COORDINATES, R4_COORDINATES, R1_COORDINATES, R0_COORDINATES, PC0_COORDINATES);
+ if (startingPoint.equals("PC0")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ break;
+
+ case "PC0--R0--R1--R2--R4--R6--PC2":
+ part1 = List.of(PC0_COORDINATES, R0_COORDINATES, R1_COORDINATES, R2_COORDINATES, R4_COORDINATES, R6_COORDINATES, PC2_COORDINATES);
+ part2 = List.of(PC2_COORDINATES, R6_COORDINATES, R4_COORDINATES, R2_COORDINATES, R1_COORDINATES, R0_COORDINATES, PC0_COORDINATES);
+ if (startingPoint.equals("PC0")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ break;
+
+ // PC1 to PC2 paths
+ case "PC1--R3--R2--R4--R6--PC2":
+ part1 = List.of(PC1_COORDINATES, R3_COORDINATES, R2_COORDINATES, R4_COORDINATES, R6_COORDINATES, PC2_COORDINATES);
+ part2 = List.of(PC2_COORDINATES, R6_COORDINATES, R4_COORDINATES, R2_COORDINATES, R3_COORDINATES, PC1_COORDINATES);
+ if (startingPoint.equals("PC1")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ break;
+
+ case "PC1--R3--R2--R1--R4--R6--PC2":
+ part1 = List.of(PC1_COORDINATES, R3_COORDINATES, R2_COORDINATES, R1_COORDINATES, R4_COORDINATES, R6_COORDINATES, PC2_COORDINATES);
+ part2 = List.of(PC2_COORDINATES, R6_COORDINATES, R4_COORDINATES, R1_COORDINATES, R2_COORDINATES, R3_COORDINATES, PC1_COORDINATES);
+ if (startingPoint.equals("PC1")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ break;
+
+ case "PC1--R3--R2--R1--R0--R5--R6--PC2":
+ part1 = List.of(PC1_COORDINATES, R3_COORDINATES, R2_COORDINATES, R1_COORDINATES, R0_COORDINATES, R5_COORDINATES, R6_COORDINATES, PC2_COORDINATES);
+ part2 = List.of(PC2_COORDINATES, R6_COORDINATES, R5_COORDINATES, R0_COORDINATES, R1_COORDINATES, R2_COORDINATES, R3_COORDINATES, PC1_COORDINATES);
+ if (startingPoint.equals("PC1")) {
+ pointList = Stream.concat(part1.stream(), part2.stream()).toList();
+ } else {
+ pointList = Stream.concat(part2.stream(), part1.stream()).toList();
+ }
+ break;
+
+ default:
+ System.out.println("Unknown path: " + path);
+ return;
+ }
+
+ pointList = Stream.concat(pointList.stream(), pointList.stream()).toList();
+ // Create and setup the animation
+ anim = new PacketAnimation(pointList);
+ //anim.setPreferredSize(networkPanel.getSize());
+ //anim.setSize(networkPanel.getSize());
+ anim.setOpaque(false);
+ anim.setBounds(0, 0, networkPanel.getWidth(), networkPanel.getHeight());
+
+ // Add the animation panel at index 0 (bottom layer)
+ networkPanel.add(anim, 0);
+ networkPanel.revalidate();
+ networkPanel.repaint();
+
+ // Start the animation on the EDT
+ SwingUtilities.invokeLater(anim::startAnimation);
+ }
+}
diff --git a/src/PreconfiguredNetworkPanel.java b/src/PreconfiguredNetworkPanel.java
new file mode 100644
index 0000000..55e7ebb
--- /dev/null
+++ b/src/PreconfiguredNetworkPanel.java
@@ -0,0 +1,363 @@
+import javax.swing.*;
+import java.awt.*;
+
+public class PreconfiguredNetworkPanel extends JPanel {
+ // Button size constants
+ private static final int BUTTON_WIDTH = 60;
+ private static final int BUTTON_HEIGHT = 60;
+
+ // PC Button positions
+ private static final int PC0_X = 50;
+ private static final int PC0_Y = 50;
+
+ private static final int PC1_X = 700;
+ private static final int PC1_Y = 700;
+
+ private static final int PC2_X = 1000;
+ private static final int PC2_Y = 180;
+
+ // Router Button positions
+ private static final int R0_X = 180;
+ private static final int R0_Y = 180;
+
+ private static final int R1_X = 310;
+ private static final int R1_Y = 310;
+
+ private static final int R2_X = 440;
+ private static final int R2_Y = 440;
+
+ private static final int R3_X = 570;
+ private static final int R3_Y = 570;
+
+ private static final int R4_X = 545;
+ private static final int R4_Y = 310;
+
+ private static final int R5_X = 700;
+ private static final int R5_Y = 180;
+
+ private static final int R6_X = 850;
+ private static final int R6_Y = 310;
+
+ private PrePathCalculation prePathCalculation;
+
+ Line[] wires = {
+ new Line(60, 60, 180, 180, Color.BLACK), // PC0 to R0
+ new Line(180, 180, 310, 310, Color.BLACK), // R0 to R1
+ new Line(310, 310, 440, 440, Color.BLACK), // R1 to R2
+ new Line(440, 440, 570, 570, Color.BLACK), // R2 to R3
+ new Line(570, 570, 700, 700, Color.BLACK), // R3 to PC1
+ new Line(240, 210, 730, 210, Color.BLACK), // R0 to R5
+ new Line(320, 340, 545, 340, Color.BLACK), // R1 to R4
+ new Line(545, 340, 850, 340, Color.BLACK), // R4 to R6
+ new Line(760, 240, 850, 310, Color.BLACK), // R5 to R6
+ new Line(480, 470, 570, 340, Color.BLACK), // R2 to R4
+ new Line(880, 340, 1030, 210, Color.BLACK), // R6 to PC3
+ };
+
+ PCButton[] pcButtons = getPCButtonArray(3, "PC");
+ RouterButton[] routerButtons = getRouterButtonArray(7, "R");
+
+ JLabel[] pcFa00Lables = new JLabel[pcButtons.length];
+
+ JLabel[] routerGig00Lables = new JLabel[routerButtons.length];
+ JLabel[] routerGig01Lables = new JLabel[routerButtons.length];
+ JLabel[] routerGig02Lables = new JLabel[routerButtons.length];
+
+ public PreconfiguredNetworkPanel() {
+ this.setLayout(null); // No layout, for placing items with x and y coordinates.
+ addRouterAndPCButtons();
+ setupPCPorts();
+ setupRouterPorts();
+ setupConnections();
+ createPCFa00Labels();
+ createRouterAllLabels();
+ placePCFa00Labels();
+ placeRouterAllLabels();
+ placeCostLabels();
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ for (Line line : wires) {
+ line.draw(g); // Draw stored lines
+ }
+ }
+
+ private static RouterButton[] getRouterButtonArray(int count, String name) {
+ RouterButton[] routers = new RouterButton[count];
+
+ // count-- is post decrement, meaning the current count variable is used, then it is decremented.
+ while (count-- > 0) {
+ routers[count] = new RouterButton(name + (count));
+ }
+ return routers;
+ }
+
+ private PCButton[] getPCButtonArray(int count, String name) {
+ PCButton[] pcButtons = new PCButton[count];
+
+ // count-- is post decrement, meaning the current count variable is used, then it is decremented.
+ while (count-- > 0) {
+ pcButtons[count] = new PCButton(name + (count), this);
+ }
+ return pcButtons;
+ }
+
+ private void setupPCPorts() {
+ pcButtons[0].getPC().setPortFA00(new IPAddress("192.168.1.254"), new SubnetMask("255.255.255.0"));
+ pcButtons[1].getPC().setPortFA00(new IPAddress("192.168.10.254"), new SubnetMask("255.255.255.0"));
+ pcButtons[2].getPC().setPortFA00(new IPAddress("192.168.19.254"), new SubnetMask("255.255.255.0"));
+ }
+
+ private void setupRouterPorts() {
+ // Setup all the router IP Address and Subnet Masks for all of their ports.
+ for (int i = 0; i < routerButtons.length; i++) {
+ Router router = routerButtons[i].getRouter();
+ router.setPort00(new IPAddress("192.168.%d.1".formatted((i * 3) + 1)), new SubnetMask("255.255.255.0"));
+ router.setPort01(new IPAddress("192.168.%d.1".formatted((i * 3) + 2)), new SubnetMask("255.255.255.0"));
+ router.setPort02(new IPAddress("192.168.%d.1".formatted((i * 3) + 3)), new SubnetMask("255.255.255.0"));
+ }
+ }
+
+ private void setupConnections() {
+ // Connect the router NIC to the PC NIC.
+ // PC0 to R0 Gig00
+ routerButtons[0].getRouter().getPort00().setConnection(pcButtons[0].getPC().getPortFA00());
+ pcButtons[0].getPC().getPortFA00().setConnection(routerButtons[0].getRouter().getPort00());
+ // PC1 to R3 Gig00
+ routerButtons[3].getRouter().getPort00().setConnection(pcButtons[1].getPC().getPortFA00());
+ pcButtons[1].getPC().getPortFA00().setConnection(routerButtons[3].getRouter().getPort00());
+ // PC2 to R6 Gig00
+ routerButtons[6].getRouter().getPort00().setConnection(pcButtons[2].getPC().getPortFA00());
+ pcButtons[2].getPC().getPortFA00().setConnection(routerButtons[6].getRouter().getPort00());
+ // Connect Router NIC ot the other Router NIC.
+ // R0 Gig01 to R1 Gig00
+ routerButtons[0].getRouter().getPort01().setConnection(routerButtons[1].getRouter().getPort00());
+ routerButtons[1].getRouter().getPort00().setConnection(routerButtons[0].getRouter().getPort01());
+ // R0 Gig02 to R5 Gig00
+ routerButtons[0].getRouter().getPort02().setConnection(routerButtons[5].getRouter().getPort00());
+ routerButtons[5].getRouter().getPort00().setConnection(routerButtons[0].getRouter().getPort02());
+ // R1 Gig01 to R2 Gig00
+ routerButtons[1].getRouter().getPort01().setConnection(routerButtons[2].getRouter().getPort00());
+ routerButtons[2].getRouter().getPort00().setConnection(routerButtons[1].getRouter().getPort01());
+ // R1 Gig02 to R4 Gig00
+ routerButtons[1].getRouter().getPort02().setConnection(routerButtons[4].getRouter().getPort00());
+ routerButtons[4].getRouter().getPort00().setConnection(routerButtons[1].getRouter().getPort02());
+ // R2 Gig01 to R4 Gig01
+ routerButtons[2].getRouter().getPort01().setConnection(routerButtons[4].getRouter().getPort01());
+ routerButtons[4].getRouter().getPort01().setConnection(routerButtons[2].getRouter().getPort01());
+ // R2 Gig01 to R3 Gig00
+ routerButtons[2].getRouter().getPort01().setConnection(routerButtons[3].getRouter().getPort00());
+ routerButtons[3].getRouter().getPort00().setConnection(routerButtons[2].getRouter().getPort01());
+ // R5 Gig01 to R6 Gig00
+ routerButtons[5].getRouter().getPort01().setConnection(routerButtons[6].getRouter().getPort00());
+ routerButtons[6].getRouter().getPort00().setConnection(routerButtons[5].getRouter().getPort01());
+ // R4 Gig02 to R6 Gig01
+ routerButtons[4].getRouter().getPort02().setConnection(routerButtons[6].getRouter().getPort01());
+ routerButtons[6].getRouter().getPort01().setConnection(routerButtons[4].getRouter().getPort02());
+ }
+
+ private void addRouterAndPCButtons() {
+ pcButtons[0].setBounds(new Rectangle(PC0_X, PC0_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ routerButtons[0].setBounds(new Rectangle(R0_X, R0_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ routerButtons[1].setBounds(new Rectangle(R1_X, R1_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ routerButtons[2].setBounds(new Rectangle(R2_X, R2_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ routerButtons[3].setBounds(new Rectangle(R3_X, R3_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ pcButtons[1].setBounds(new Rectangle(PC1_X, PC1_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ routerButtons[4].setBounds(new Rectangle(R4_X, R4_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ routerButtons[5].setBounds(new Rectangle(R5_X, R5_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ routerButtons[6].setBounds(new Rectangle(R6_X, R6_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ pcButtons[2].setBounds(new Rectangle(PC2_X, PC2_Y, BUTTON_WIDTH, BUTTON_HEIGHT));
+
+ for (JButton button : routerButtons) {
+ this.add(button);
+ }
+
+ for (JButton button : pcButtons) {
+ this.add(button);
+ }
+ }
+
+ private void createPCFa00Labels() {
+ // Set the name for all the PC labels
+ for (int i = 0; i < pcFa00Lables.length; i++) {
+ pcFa00Lables[i] = new JLabel("Fa 0/0");
+ }
+ }
+
+ private void createRouterAllLabels() {
+ for (int i = 0; i < routerButtons.length; i++) {
+ routerGig00Lables[i] = new JLabel("Gig 0/0");
+ }
+
+ for (int i = 0; i < routerButtons.length; i++) {
+ routerGig01Lables[i] = new JLabel("Gig 0/1");
+ }
+
+ for (int i = 0; i < routerButtons.length; i++) {
+ routerGig02Lables[i] = new JLabel("Gig 0/2");
+ }
+ }
+
+ private void placePCFa00Labels() {
+ pcFa00Lables[0].setBounds(70, 90, 60, 60);
+
+ pcFa00Lables[1].setBounds(700, 660, 60, 60);
+
+ pcFa00Lables[2].setBounds(1000, 220, 60, 60);
+
+ for (JLabel label : pcFa00Lables) {
+ this.add(label);
+ }
+ }
+
+ private void placeRouterAllLabels() {
+ // R0
+ routerGig00Lables[0].setBounds(130, 150, 60, 60);
+ routerGig01Lables[0].setBounds(200, 220, 60, 60);
+ routerGig02Lables[0].setBounds(240, 160, 60, 60);
+ // R1
+ routerGig00Lables[1].setBounds(260, 280, 60, 60);
+ routerGig01Lables[1].setBounds(330, 350, 60, 60);
+ routerGig02Lables[1].setBounds(370, 290, 60, 60);
+ // R2
+ routerGig00Lables[2].setBounds(390, 410, 60, 60);
+ routerGig01Lables[2].setBounds(460, 480, 60, 60);
+ routerGig02Lables[2].setBounds(500, 420, 60, 60);
+ // R3
+ routerGig00Lables[3].setBounds(520, 540, 60, 60);
+ routerGig01Lables[3].setBounds(590, 610, 60, 60);
+ // R4
+ routerGig00Lables[4].setBounds(500, 290, 60, 60);
+ routerGig01Lables[4].setBounds(550, 350, 60, 60);
+ routerGig02Lables[4].setBounds(610, 290, 60, 60);
+ // R5
+ routerGig00Lables[5].setBounds(650, 160, 60, 60);
+ routerGig01Lables[5].setBounds(720, 220, 60, 60);
+ // R6
+ routerGig00Lables[6].setBounds(800, 280, 60, 60);
+ routerGig01Lables[6].setBounds(800, 320, 60, 60);
+ routerGig02Lables[6].setBounds(910, 290, 60, 60);
+
+ for (JLabel label : routerGig00Lables) {
+ this.add(label);
+ }
+
+ for (JLabel label : routerGig01Lables) {
+ this.add(label);
+ }
+
+ for (JLabel label : routerGig02Lables) {
+ this.add(label);
+ }
+ }
+
+ public void placeCostLabels() {
+ // Remove existing cost labels
+ Component[] components = this.getComponents();
+ for (Component component : components) {
+ if (component instanceof JLabel && ((JLabel) component).getText().contains(" to ")) {
+ this.remove(component);
+ }
+ }
+
+ // Create new PrePathCalculation with current router configurations
+ prePathCalculation = new PrePathCalculation(getRouters());
+
+ int R0_R1_COST = prePathCalculation.getR0R1Cost();
+ int R0_R5_COST = prePathCalculation.getR0R5Cost();
+ int R1_R2_COST = prePathCalculation.getR1R2Cost();
+ int R1_R4_COST = prePathCalculation.getR1R4Cost();
+ int R2_R3_COST = prePathCalculation.getR2R3Cost();
+ int R2_R4_COST = prePathCalculation.getR2R4Cost();
+ int R4_R6_COST = prePathCalculation.getR4R6Cost();
+ int R5_R6_COST = prePathCalculation.getR5R6Cost();
+
+ JLabel[] costLabels = {
+ new JLabel("R0 to R1: " + R0_R1_COST),
+ new JLabel("R0 to R5: " + R0_R5_COST),
+ new JLabel("R1 to R2: " + R1_R2_COST),
+ new JLabel("R1 to R4: " + R1_R4_COST),
+ new JLabel("R2 to R3: " + R2_R3_COST),
+ new JLabel("R2 to R4: " + R2_R4_COST),
+ new JLabel("R4 to R6: " + R4_R6_COST),
+ new JLabel("R5 to R6: " + R5_R6_COST)
+ };
+
+ costLabels[0].setBounds(((R0_X + R1_X) / 2) - 50, ((R0_Y + R1_Y) / 2) + 20, 120, 60);
+ costLabels[1].setBounds(((R0_X + R5_X) / 2), ((R0_Y + R5_Y) / 2) + 20, 120, 60);
+ costLabels[2].setBounds(((R1_X + R2_X) / 2) - 50, ((R1_Y + R2_Y) / 2) + 20, 120, 60);
+ costLabels[3].setBounds(((R1_X + R4_X) / 2), ((R1_Y + R4_Y) / 2) + 20, 120, 60);
+ costLabels[4].setBounds(((R2_X + R3_X) / 2) - 50, ((R2_Y + R3_Y) / 2) + 20, 120, 60);
+ costLabels[5].setBounds(((R2_X + R4_X) / 2) + 50, ((R2_Y + R4_Y) / 2) + 20, 120, 60);
+ costLabels[6].setBounds(((R4_X + R6_X) / 2), ((R4_Y + R6_Y) / 2) + 20, 120, 60);
+ costLabels[7].setBounds(((R5_X + R6_X) / 2) - 50, ((R5_Y + R6_Y) / 2) + 20, 120, 60);
+
+ for (JLabel label : costLabels) {
+ this.add(label);
+ }
+
+ // Force a repaint to show the updated labels
+ this.revalidate();
+ this.repaint();
+ }
+
+ public Router[] getRouters() {
+ Router[] routers = new Router[routerButtons.length];
+ for (int i = 0; i < routerButtons.length; i++) {
+ routers[i] = routerButtons[i].getRouter();
+ }
+ return routers;
+ }
+
+ public PC[] getPCs() {
+ PC[] pcs = new PC[pcButtons.length];
+ for (int i = 0; i < pcButtons.length; i++) {
+ pcs[i] = pcButtons[i].getPC();
+ }
+ return pcs;
+ }
+
+ // Coordinate getter methods for devices.
+ public Point getDeviceCoordinates(String deviceName) {
+ switch (deviceName) {
+ case "R0":
+ return new Point(R0_X, R0_Y);
+ case "R1":
+ return new Point(R1_X, R1_Y);
+ case "R2":
+ return new Point(R2_X, R2_Y);
+ case "R3":
+ return new Point(R3_X, R3_Y);
+ case "R4":
+ return new Point(R4_X, R4_Y);
+ case "R5":
+ return new Point(R5_X, R5_Y);
+ case "R6":
+ return new Point(R6_X, R6_Y);
+ case "PC0":
+ return new Point(PC0_X, PC0_Y);
+ case "PC1":
+ return new Point(PC1_X, PC1_Y);
+ case "PC2":
+ return new Point(PC2_X, PC2_Y);
+ default:
+ return null;
+ }
+ }
+
+ // Get button dimensions
+ public Dimension getButtonDimension() {
+ return new Dimension(BUTTON_WIDTH, BUTTON_HEIGHT);
+ }
+}
\ No newline at end of file
diff --git a/src/RID.java b/src/RID.java
new file mode 100644
index 0000000..884e3e5
--- /dev/null
+++ b/src/RID.java
@@ -0,0 +1,120 @@
+public class RID {
+ //private String ipAddress;
+ private byte[] rid = new byte[4];
+
+ public RID(String rid) {
+ // constructor used for checking that each segment is the right type and in the right range.
+ // if a wrong type is entered, it will throw out an error into main, which
+ // can be caught and used for error handling.
+ if (validIpAddress(rid)) {
+ this.rid = ipStringToByteArray(rid);
+ } else {
+ throw new IllegalArgumentException("Each segment must be between 0 and 255.");
+ }
+ }
+
+ public RID() {
+ this.rid = new byte[4];
+ }
+
+ public byte[] getRid() {
+ return rid;
+ }
+
+ public String toString() {
+ // Needs to be converted to an unsigned int, to not have minus values. As bytes are represented in negatives.
+ String byte0 = Integer.toString(Byte.toUnsignedInt(rid[0]));
+ String byte1 = Integer.toString(Byte.toUnsignedInt(rid[1]));
+ String byte2 = Integer.toString(Byte.toUnsignedInt(rid[2]));
+ String byte3 = Integer.toString(Byte.toUnsignedInt(rid[3]));
+
+ return byte0 + "." + byte1 + "." + byte2 + "." + byte3;
+ }
+
+ public void setRid(String rid) {
+ //this.ipAddress = ipAddress;
+ if (validIpAddress(rid)) {
+ this.rid = ipStringToByteArray(rid);
+ } else {
+ throw new IllegalArgumentException("Each segment must be between 0 and 255.");
+ }
+ }
+
+ public void setByte3(byte byte3) {
+ this.rid[3] = byte3;
+ }
+
+ public void setByte2(byte byte2) {
+ this.rid[2] = byte2;
+ }
+
+ public void setByte1(byte byte1) {
+ this.rid[1] = byte1;
+ }
+
+ public void setByte0(byte byte0) {
+ this.rid[0] = byte0;
+ }
+
+ private boolean validIpAddress(String rid) {
+ // used for checking if the entered IP address is in the correct
+ // format
+
+ // Regex pattern that will accept 0.0.0.0 to 999.999.999.999
+ String regex = "[0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}[.][0-9]{1,3}";
+
+ // This will check if the pattern is at least correct, but won't check
+ // if the numbers within the pattern are below 255
+ if (!rid.matches(regex)) {
+ return false;
+ }
+
+ // This will check if the numbers within the rid are not too big
+ // Will split the string at hte "." and will have 4 digits
+ String[] arrRid = rid.split("[.]", 4);
+
+ // Each digit within the array will be converted from a String to an in
+ // and will be checked if it is not over 255
+ for (String digit : arrRid) {
+ int number = Integer.parseInt(digit);
+ if (number > 0x255) {
+ return false;
+ }
+ }
+
+ // if all checks are complete, then the RID format is correct
+ return true;
+ }
+
+ private byte[] ipStringToByteArray(String strRid) {
+
+ byte[] rid = new byte[4];
+ // Splits the ip address string at every ".", of a maximum of 4.
+ String[] strBytes = strRid.split("[.]", 4);
+
+ for (int i = 0; i < strBytes.length; i++) {
+ rid[i] = (byte) Integer.parseInt(strBytes[i]);
+ }
+
+ return rid;
+ }
+
+ // Overrides the original equals method, which only compares memory locations matching, instead we also need to compare,
+ // if each instance is the same, while still being in another memory location.
+ public boolean equals(Object object) {
+ // Checks if both references (this and object) point to the same memory location, if so they are the same.
+ if(this == object) return true;
+ // Checks if the object is null or if the objects are of the same class, if so, then they are not equal, so
+ // return false.
+ if(object == null || this.getClass() != object.getClass()) return false;
+ // Cast the object to the SubnetMask object class.
+ RID ipAddress = (RID) object;
+ // Check if all the subnet mask values match, if not then return false.
+ if(this.rid[0] != ipAddress.getRid()[0]) return false;
+ if(this.rid[1] != ipAddress.getRid()[1]) return false;
+ if(this.rid[2] != ipAddress.getRid()[2]) return false;
+ if(this.rid[3] != ipAddress.getRid()[3]) return false;
+ // Once all conditions are met, then the objects equal.
+ return true;
+ }
+}
diff --git a/src/Router.java b/src/Router.java
index 7cc4b57..4780e3e 100644
--- a/src/Router.java
+++ b/src/Router.java
@@ -2,6 +2,7 @@
import java.util.List;
public class Router extends Device {
+ RID rid;
public Router(String name) {
// Use the parent class constructor to add the name variable within the Device class.
@@ -9,30 +10,81 @@ public Router(String name) {
// Set up the NIC for the Router, which is Gig 0/0, Gig 0/1, Gig 0/2. There is only a name for them set, as the
// user should be able to set the IP and subnet mask at a later time.
- NIC gig00 = new NIC("GigabitEthernet 0/0");
- NIC gig01 = new NIC("GigabitEthernet 0/1");
- NIC gig02 = new NIC("GigabitEthernet 0/2");
+ NIC port00 = new NIC("GigabitEthernet", this);
+ NIC port01 = new NIC("GigabitEthernet", this);
+ NIC port02 = new NIC("GigabitEthernet", this);
// Add the NICs to the ArrayList of the nic list within the parent class.
- super.setNICList(new ArrayList<>(List.of(gig00, gig01, gig02)));
+ super.setNICList(new ArrayList<>(List.of(port00, port01, port02)));
}
- public NIC getPortGig00() { return super.getNICList().get(0); }
+ public ArrayList getNICList() { return super.getNICList(); }
- public void setPortGig00(IPAddress ipAddress, SubnetMask subnetMask) {
+ public NIC getPort00() { return super.getNICList().get(0); }
+
+ public void setPort00(IPAddress ipAddress, SubnetMask subnetMask) {
+ super.getNICList().get(0).setIpAddress(ipAddress);
+ super.getNICList().get(0).setSubnetMask(subnetMask);
+ }
+
+ public void setPort00IPAddress(IPAddress ipAddress) {
super.getNICList().get(0).setIpAddress(ipAddress);
+ }
+
+ public void setPort00SubnetMask(SubnetMask subnetMask) {
super.getNICList().get(0).setSubnetMask(subnetMask);
}
- public NIC getPortGig01() { return super.getNICList().get(1); }
- public void setPortGig01(IPAddress ipAddress, SubnetMask subnetMask) {
+ public void setPort00Type(String type) {
+ super.getNICList().get(0).setType(type);
+ }
+
+ public void setPort01(IPAddress ipAddress, SubnetMask subnetMask) {
+ super.getNICList().get(1).setIpAddress(ipAddress);
+ super.getNICList().get(1).setSubnetMask(subnetMask);
+ }
+
+ public NIC getPort01() { return super.getNICList().get(1); }
+
+ public void setPort01IPAddress(IPAddress ipAddress) {
super.getNICList().get(1).setIpAddress(ipAddress);
+ }
+
+ public void setPort01SubnetMask(SubnetMask subnetMask) {
super.getNICList().get(1).setSubnetMask(subnetMask);
}
- public NIC getPortGig02() { return super.getNICList().get(2); }
- public void setPortGig02(IPAddress ipAddress, SubnetMask subnetMask) {
+ public void setPort01Type(String type) {
+ super.getNICList().get(1).setType(type);
+ }
+
+ public NIC getPort02() { return super.getNICList().get(2); }
+
+ public void setPort02(IPAddress ipAddress, SubnetMask subnetMask) {
super.getNICList().get(2).setIpAddress(ipAddress);
super.getNICList().get(2).setSubnetMask(subnetMask);
}
-}
+
+ public void setPort02IPAddress(IPAddress ipAddress) {
+ super.getNICList().get(2).setIpAddress(ipAddress);
+ }
+
+ public void setPort02SubnetMask(SubnetMask subnetMask) {
+ super.getNICList().get(2).setSubnetMask(subnetMask);
+ }
+
+ public void setPort02Type(String type) {
+ super.getNICList().get(2).setType(type);
+ }
+
+ public void setRid(RID rid) {
+ this.rid = rid;
+ }
+
+ public String getRid() {
+ if (this.rid == null) {
+ return "";
+ }
+ return rid.toString();
+ }
+}
\ No newline at end of file
diff --git a/src/RouterButton.java b/src/RouterButton.java
new file mode 100644
index 0000000..f2faeed
--- /dev/null
+++ b/src/RouterButton.java
@@ -0,0 +1,74 @@
+import javax.swing.*;
+import java.awt.*;
+
+public class RouterButton extends JButton {
+ Router router;
+
+ public RouterButton(String name) {
+ super();
+ this.router = new Router(name);
+
+ // Set the router icon
+ ImageIcon icon = new ImageIcon("images/icons8-router-symbol-50.png");
+ Image scaledImage = icon.getImage().getScaledInstance(50, 50, Image.SCALE_SMOOTH);
+ // This method comes from the AbstractButton class.
+ setIcon(new ImageIcon(scaledImage));
+
+ // Remove the border around the button.
+ setBorderPainted(false);
+ // Match the same colour as the background.
+ setBackground(new Color(240, 240, 240));
+
+ // Set tooltip to show the router name
+ setToolTipText(name);
+
+ super.addActionListener(e -> {
+ String[] labels = {
+ "Name",
+ router.getPort00().getType() + " 0/0 IP Address",
+ router.getPort00().getType() + " 0/0 Subnet Mask",
+ router.getPort00().getType() + " 0/0 MAC Address",
+ router.getPort01().getType() + " 0/1 IP Address",
+ router.getPort01().getType() + " 0/1 Subnet Mask",
+ router.getPort01().getType() + " 0/1 MAC Address",
+ router.getPort02().getType() + " 0/2 IP Address",
+ router.getPort02().getType() + " 0/2 Subnet Mask",
+ router.getPort02().getType() + " 0/2 MAC Address",
+ "RID",
+ };
+
+ String[] fields = {
+ router.getName(),
+ router.getPort00().getIpAddress() == null ? "" : router.getPort00().getIpAddress().toString(),
+ router.getPort00().getSubnetMask() == null ? "" : router.getPort00().getSubnetMask().toString(),
+ router.getPort00().getMacAddress() == null ? "" : router.getPort00().getMacAddress().toString(),
+ router.getPort01().getIpAddress() == null ? "" : router.getPort01().getIpAddress().toString(),
+ router.getPort01().getSubnetMask() == null ? "" : router.getPort01().getSubnetMask().toString(),
+ router.getPort01().getMacAddress() == null ? "" : router.getPort01().getMacAddress().toString(),
+ router.getPort02().getIpAddress() == null ? "" : router.getPort02().getIpAddress().toString(),
+ router.getPort02().getSubnetMask() == null ? "" : router.getPort02().getSubnetMask().toString(),
+ router.getPort02().getMacAddress() == null ? "" : router.getPort02().getMacAddress().toString(),
+ router.getRid() == null ? "" : router.getRid(),
+ };
+
+ RouterInfoFrame routerInfoFrame = new RouterInfoFrame(
+ router.getName(),
+ labels,
+ fields,
+ router,
+ this
+ );
+
+ routerInfoFrame.setEditable(router.getPort00().getType() + " 0/0 MAC Address", false);
+ routerInfoFrame.setEditable(router.getPort01().getType() + " 0/1 MAC Address", false);
+ routerInfoFrame.setEditable(router.getPort02().getType() + " 0/2 MAC Address", false);
+ routerInfoFrame.setEditable("Port Type", false);
+
+ routerInfoFrame.setVisible(true);
+ });
+ }
+
+ public Router getRouter() {
+ return router;
+ }
+}
\ No newline at end of file
diff --git a/src/RouterInfoFrame.java b/src/RouterInfoFrame.java
new file mode 100644
index 0000000..6ddeb66
--- /dev/null
+++ b/src/RouterInfoFrame.java
@@ -0,0 +1,160 @@
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+
+public class RouterInfoFrame extends JFrame {
+ private ArrayList infoFields = new ArrayList<>();
+ private JButton saveButton = new JButton("Save");
+ private JButton editPortTypeButton = new JButton("Edit PortType");
+
+ public RouterInfoFrame(String title, String[] labels, String[] fields, Router router, RouterButton routerButton) {
+ if (labels.length != fields.length) {
+ throw new IllegalArgumentException("Number of labels and fields do not match");
+ }
+
+ super.setTitle(title);
+ super.setSize(500, 500);
+ super.setLocationRelativeTo(null); // Make it center.
+ super.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // DISPOSE_ON_CLOSE Make sure the whole app doesn't shut down.
+ super.setResizable(false);
+
+ JTabbedPane tabs = new JTabbedPane();
+ JPanel generalInformationPanel = new JPanel();
+ generalInformationPanel.setLayout(new GridLayout(0, 1));
+
+ for (int i = 0; i < labels.length; i++) {
+ infoFields.add(new InfoField(labels[i], fields[i]));
+ // Add the JLabel and JTextField to the JFrame.
+ generalInformationPanel.add(infoFields.get(i));
+ }
+ //setDeviceInfoTab(tabs);
+ tabs.addTab("General", generalInformationPanel);
+
+ OSPFNeighboursScrollPane ospfNeighboursScrollPane = new OSPFNeighboursScrollPane(router);
+ tabs.addTab("OSPF Neighbours", ospfNeighboursScrollPane);
+
+ super.add(tabs);
+
+ this.saveButton.addActionListener(e -> {
+ System.out.println("Saving ");
+ router.setName(infoFields.get(0).getTextField().getText());
+ routerButton.setText(infoFields.get(0).getTextField().getText());
+ this.setTitle(infoFields.get(0).getTextField().getText());
+ try {
+ IPAddress ipGig00 = new IPAddress(infoFields.get(1).getTextField().getText());
+ router.setPort00IPAddress(ipGig00);
+ } catch (IllegalArgumentException exception) {
+ System.out.println("Invalid IP address for Gig0/0");
+ }
+ try {
+ SubnetMask subnetGig00 = new SubnetMask(infoFields.get(2).getTextField().getText());
+ router.setPort00SubnetMask(subnetGig00);
+ } catch (IllegalArgumentException exception) {
+ System.out.println("Invalid subnet mask for Gig0/0");
+ }
+ try {
+ IPAddress ipGig01 = new IPAddress(infoFields.get(4).getTextField().getText());
+ router.setPort01IPAddress(ipGig01);
+ } catch (IllegalArgumentException exception) {
+ System.out.println("Invalid IP address for Gig0/1");
+ }
+ try {
+ SubnetMask subnetGig01 = new SubnetMask(infoFields.get(5).getTextField().getText());
+ router.setPort01SubnetMask(subnetGig01);
+ } catch (IllegalArgumentException exception) {
+ System.out.println("Invalid subnet mask for Gig0/1");
+ }
+ try {
+ IPAddress ipGig02 = new IPAddress(infoFields.get(7).getTextField().getText());
+ router.setPort02IPAddress(ipGig02);
+ } catch (IllegalArgumentException exception) {
+ System.out.println("Invalid IP address for Gig0/2");
+ }
+ try {
+ SubnetMask subnetGig02 = new SubnetMask(infoFields.get(8).getTextField().getText());
+ router.setPort02SubnetMask(subnetGig02);
+ } catch (IllegalArgumentException exception) {
+ System.out.println("Invalid subnet mask for Gig0/2");
+ }
+ try {
+ RID rid = new RID(infoFields.get(9).getTextField().getText());
+ router.setRid(rid);
+ System.out.println(router.getRid());
+ } catch (IllegalArgumentException exceptions) {
+ System.out.println("Invalid RID");
+ }
+ });
+
+ generalInformationPanel.add(saveButton);
+
+ this.editPortTypeButton.addActionListener(e -> {
+ JFrame editPortTypeFrame = new JFrame("Edit Port Type");
+ editPortTypeFrame.setSize(300, 150);
+ editPortTypeFrame.setLocationRelativeTo(null);
+ editPortTypeFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
+ editPortTypeFrame.setResizable(false);
+ editPortTypeFrame.setLayout(new GridLayout(0, 1));
+
+ JComboBox port00TypeComboBox = new JComboBox<>(new String[]{"Port 00: GigabitEthernet", "Port 00: FastEthernet"});
+ JComboBox port01TypeComboBox = new JComboBox<>(new String[]{"Port 01: GigabitEthernet", "Port 01: FastEthernet"});
+ JComboBox port02TypeComboBox = new JComboBox<>(new String[]{"Port 02: GigabitEthernet", "Port 02: FastEthernet"});
+
+ // Set the current port types in the combo boxes
+ String currentPort00Type = router.getPort00().getType();
+ String currentPort01Type = router.getPort01().getType();
+ String currentPort02Type = router.getPort02().getType();
+
+ port00TypeComboBox.setSelectedItem("Port 00: " + currentPort00Type);
+ port01TypeComboBox.setSelectedItem("Port 01: " + currentPort01Type);
+ port02TypeComboBox.setSelectedItem("Port 02: " + currentPort02Type);
+
+ editPortTypeFrame.add(port00TypeComboBox);
+ editPortTypeFrame.add(port01TypeComboBox);
+ editPortTypeFrame.add(port02TypeComboBox);
+
+ JButton saveButton = new JButton("Save");
+ saveButton.addActionListener(e1 -> {
+ String port00Type = port00TypeComboBox.getSelectedItem().toString().split(": ")[1];
+ String port01Type = port01TypeComboBox.getSelectedItem().toString().split(": ")[1];
+ String port02Type = port02TypeComboBox.getSelectedItem().toString().split(": ")[1];
+
+ router.setPort00Type(port00Type);
+ router.setPort01Type(port01Type);
+ router.setPort02Type(port02Type);
+
+ // Update the labels in the info fields
+ infoFields.get(1).getLabel().setText(port00Type + " 0/0 IP Address");
+ infoFields.get(2).getLabel().setText(port00Type + " 0/0 Subnet Mask");
+ infoFields.get(3).getLabel().setText(port00Type + " 0/0 MAC Address");
+ infoFields.get(4).getLabel().setText(port01Type + " 0/1 IP Address");
+ infoFields.get(5).getLabel().setText(port01Type + " 0/1 Subnet Mask");
+ infoFields.get(6).getLabel().setText(port01Type + " 0/1 MAC Address");
+ infoFields.get(7).getLabel().setText(port02Type + " 0/2 IP Address");
+ infoFields.get(8).getLabel().setText(port02Type + " 0/2 Subnet Mask");
+ infoFields.get(9).getLabel().setText(port02Type + " 0/2 MAC Address");
+
+ // Update the cost path labels
+ PreconfiguredNetworkPanel networkPanel = (PreconfiguredNetworkPanel) routerButton.getParent();
+ networkPanel.placeCostLabels();
+
+ System.out.println("Router Port 00: " + router.getPort00().getType());
+ System.out.println("Router Port 01: " + router.getPort01().getType());
+ System.out.println("Router Port 02: " + router.getPort02().getType());
+ editPortTypeFrame.dispose();
+ });
+ editPortTypeFrame.add(saveButton);
+
+ editPortTypeFrame.setVisible(true);
+ });
+
+ generalInformationPanel.add(editPortTypeButton);
+ }
+
+ public void setEditable(String fieldLabel, boolean editable) {
+ for (InfoField infoField : infoFields) {
+ if (infoField.getLabel().getText().equals(fieldLabel)) {
+ infoField.setEditable(editable);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/SubnetMask.java b/src/SubnetMask.java
index 3e496a7..ad027a9 100644
--- a/src/SubnetMask.java
+++ b/src/SubnetMask.java
@@ -1,5 +1,5 @@
public class SubnetMask {
- private byte[] subnetMask = new byte[4];
+ private byte[] subnetMask;
public SubnetMask(String subnetMask) {
// constructor used for checking that each segment is the right type and in the right range.
diff --git a/src/gui/Main.java b/src/gui/Main.java
deleted file mode 100644
index c2acf29..0000000
--- a/src/gui/Main.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package gui;
-
-public class Main {
-}
diff --git a/test/IPAddressTest.java b/test/IPAddressTest.java
new file mode 100644
index 0000000..d3a5aaf
--- /dev/null
+++ b/test/IPAddressTest.java
@@ -0,0 +1,12 @@
+//import org.junit.jupiter.api.Test;
+//
+//import static org.junit.jupiter.api.Assertions.*;
+//
+//class IPAddressTest {
+// @Test
+// void convertFromIPAddressToString() {
+// IPAddress ipAddress = new IPAddress("192.168.1.1");
+// // Check if the toString method still creates the correct formatting.
+// assertEquals("192.168.1.1", ipAddress.toString());
+// }
+//}
\ No newline at end of file