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