diff --git a/chameleon-server/chameleon-vision.iml b/chameleon-server/chameleon-vision.iml index e863282a1..445efaa82 100644 --- a/chameleon-server/chameleon-vision.iml +++ b/chameleon-server/chameleon-vision.iml @@ -11,6 +11,7 @@ + @@ -36,6 +37,7 @@ + diff --git a/chameleon-server/pom.xml b/chameleon-server/pom.xml index d02cdfc4e..bdc1ad0a9 100644 --- a/chameleon-server/pom.xml +++ b/chameleon-server/pom.xml @@ -86,6 +86,11 @@ commons-math3 3.6.1 + + commons-io + commons-io + RELEASE + org.msgpack msgpack-core diff --git a/chameleon-server/src/main/java/com/chameleonvision/network/LinuxNetworking.java b/chameleon-server/src/main/java/com/chameleonvision/network/LinuxNetworking.java index 42998a9a0..2794f0c9a 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/network/LinuxNetworking.java +++ b/chameleon-server/src/main/java/com/chameleonvision/network/LinuxNetworking.java @@ -1,73 +1,102 @@ package com.chameleonvision.network; +import org.apache.commons.io.FileUtils; + +import java.io.File; import java.io.IOException; +import java.net.InetAddress; import java.net.SocketException; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class LinuxNetworking extends SysNetworking { + private static final String PATH = "/etc/dhcpcd.conf"; - @Override - public boolean setDHCP() { - String[] clearArgs = { "addr", "flush", "dev", networkInterface.name }; - try { - int clearRetCode = shell.execute("ip", clearArgs); - int dhcpRetCode = shell.execute("dhclient", networkInterface.name); - return clearRetCode == 0 && dhcpRetCode == 0; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } + @Override + public boolean setDHCP() { + File dhcpConf = new File(PATH); + if (dhcpConf.exists()) { + try { + List lines = FileUtils.readLines(dhcpConf, StandardCharsets.UTF_8); + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i); + if (line.contains("interface " + networkInterface.name)) { + lines.remove(i); + for (int j = i; j < lines.size(); j++) { + String subInterface = lines.get(j); + if (subInterface.contains("static ip_address") || subInterface.contains("static routers")) { + lines.remove(j); + j--; + } + if (subInterface.contains("interface")) { + break; + } + } + FileUtils.writeLines(dhcpConf, lines); + return true; + } + } + } catch (IOException e) { + e.printStackTrace(); + return false; + } - @Override - public boolean setHostname(String newHostname) { - String[] setHostnameArgs = { "set-hostname", newHostname }; - try { - var setHostnameRetCode = shell.execute("hostnamectl", setHostnameArgs); - return setHostnameRetCode == 0; - } catch(Exception e) { - e.printStackTrace(); - return false; - } - } + } else { + System.err.println("dhcpcd5 is not installed cant set ip"); + return false; + } + return true; + } - @Override - public boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) { - try { - String[] clearArgs = { "addr", "flush", "dev", networkInterface.name }; - String[] setIPArgs = { "addr", "add", String.format("%s/%s", ipAddress, netmask), "broadcast", broadcast, "dev", networkInterface.name }; - String[] setGatewayArgs = { "route", "replace", "default", "via", gateway, "dev", networkInterface.name }; + @Override + public boolean setHostname(String newHostname) { + String[] setHostnameArgs = {"set-hostname", newHostname}; + try { + var setHostnameRetCode = shell.execute("hostnamectl", setHostnameArgs); + return setHostnameRetCode == 0; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } - int clearRetCode = shell.execute("ip", clearArgs); - int setIPRetCode = shell.execute("ip", setIPArgs); - int setGatewayRetCode = shell.execute("ip", setGatewayArgs); + @Override + public boolean setStatic(String ipAddress, String netmask, String gateway) { + setDHCP(); // clean up old static interface + File dhcpConf = new File(PATH); + try { + List lines = FileUtils.readLines(dhcpConf, StandardCharsets.UTF_8); + lines.add("interface " + networkInterface.name); + InetAddress iNetMask = InetAddress.getByName(netmask); + int prefix = NetmaskToCIDR.convertNetmaskToCIDR(iNetMask); + lines.add("static ip_address " + ipAddress + "/" + prefix); + lines.add("static routers " + gateway); + FileUtils.writeLines(dhcpConf, lines); + } catch (IOException e) { + e.printStackTrace(); + } + return false; + } - return clearRetCode == 0 && setIPRetCode == 0 && setGatewayRetCode == 0; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - @Override - public List getNetworkInterfaces() throws SocketException { - List netInterfaces; - try { - netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces()); - } catch (SocketException e) { - return null; - } + @Override + public List getNetworkInterfaces() throws SocketException { + List netInterfaces; + try { + netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces()); + } catch (SocketException e) { + return null; + } + List goodInterfaces = new ArrayList<>(); - List goodInterfaces = new ArrayList<>(); + for (var netInterface : netInterfaces) { + if (netInterface.getDisplayName().contains("lo")) continue; + if (!netInterface.isUp()) continue; + goodInterfaces.add(netInterface); + } + return goodInterfaces; - for (var netInterface : netInterfaces) { - if (netInterface.getDisplayName().contains("lo")) continue; - if (!netInterface.isUp()) continue; - goodInterfaces.add(netInterface); - } - return goodInterfaces; - - } + } } diff --git a/chameleon-server/src/main/java/com/chameleonvision/network/NetmaskToCIDR.java b/chameleon-server/src/main/java/com/chameleonvision/network/NetmaskToCIDR.java new file mode 100644 index 000000000..84673605f --- /dev/null +++ b/chameleon-server/src/main/java/com/chameleonvision/network/NetmaskToCIDR.java @@ -0,0 +1,29 @@ +package com.chameleonvision.network; + +import java.net.InetAddress; + +public class NetmaskToCIDR { + //code belongs to https://stackoverflow.com/questions/19531411/calculate-cidr-from-a-given-netmask-java + public static int convertNetmaskToCIDR(InetAddress netmask) { + + byte[] netmaskBytes = netmask.getAddress(); + int cidr = 0; + boolean zero = false; + for (byte b : netmaskBytes) { + int mask = 0x80; + + for (int i = 0; i < 8; i++) { + int result = b & mask; + if (result == 0) { + zero = true; + } else if (zero) { + throw new IllegalArgumentException("Invalid netmask."); + } else { + cidr++; + } + mask >>>= 1; + } + } + return cidr; + } +} diff --git a/chameleon-server/src/main/java/com/chameleonvision/network/NetworkManager.java b/chameleon-server/src/main/java/com/chameleonvision/network/NetworkManager.java index d505199cd..60a99b8f1 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/network/NetworkManager.java +++ b/chameleon-server/src/main/java/com/chameleonvision/network/NetworkManager.java @@ -9,44 +9,45 @@ import java.util.ArrayList; import java.util.List; public class NetworkManager { - private NetworkManager() {} + private NetworkManager() { + } - private static SysNetworking networking; - private static boolean isManaged = false; + private static SysNetworking networking; + private static boolean isManaged = false; - public static void initialize(boolean manage) { - isManaged = manage; - if (!isManaged) { - return; - } + public static void initialize(boolean manage) { + isManaged = manage; + if (!isManaged) { + return; + } - Platform platform = Platform.CurrentPlatform; + Platform platform = Platform.CurrentPlatform; - if (platform.isLinux()) { - networking = new LinuxNetworking(); - } else if (platform.isWindows()) { + if (platform.isLinux()) { + networking = new LinuxNetworking(); + } else if (platform.isWindows()) { // networking = new WindowsNetworking(); System.out.println("Windows networking is not yet supported. Running unmanaged."); return; - } + } - if (networking == null) { - throw new RuntimeException("Failed to detect platform!"); - } + if (networking == null) { + throw new RuntimeException("Failed to detect platform!"); + } - List interfaces = new ArrayList<>(); - List goodInterfaces = new ArrayList<>(); + List interfaces = new ArrayList<>(); + List goodInterfaces = new ArrayList<>(); - try { - interfaces = networking.getNetworkInterfaces(); - } catch (SocketException e) { - e.printStackTrace(); - } + try { + interfaces = networking.getNetworkInterfaces(); + } catch (SocketException e) { + e.printStackTrace(); + } var teamBytes = NetworkManager.GetTeamNumberIPBytes(ConfigManager.settings.teamNumber); if (interfaces.size() > 0) { - for (var inetface : interfaces) { + for (var inetface : interfaces) { for (var inetfaceAddr : inetface.getInterfaceAddresses()) { var rawAddr = inetfaceAddr.getAddress().getAddress(); if (rawAddr.length > 4) continue; @@ -54,74 +55,53 @@ public class NetworkManager { goodInterfaces.add(new NetworkInterface(inetface, inetfaceAddr)); } } - } + } - if (goodInterfaces.size() == 0) { - isManaged = false; - System.err.println("No valid network interfaces found! Staying unmanaged."); - return; - } + if (goodInterfaces.size() == 0) { + isManaged = false; + System.err.println("No valid network interfaces found! Staying unmanaged."); + return; + } - NetworkInterface botInterface = goodInterfaces.get(0); - networking.setNetworkInterface(botInterface); - } else { - isManaged = false; - System.err.println("No valid network interfaces found! Staying unmanaged."); - return; - } - - if(!loadFromGeneralSettings()) { - isManaged = false; - System.err.println("Failed to load network settings. Staying unmanaged!"); - } - } - - private static byte[] GetTeamNumberIPBytes(int teamNumber) { - return new byte[]{(byte) (teamNumber / 100), (byte) (teamNumber % 100)}; - } - - private static boolean loadFromGeneralSettings() { - if (!isManaged) { - return true; - } - - var genSettings = ConfigManager.settings; - boolean isStatic = genSettings.connectionType.equals(NetworkIPMode.STATIC); - - if (isStatic) { - var splitIPAddr = genSettings.ip.split("\\."); - splitIPAddr[3] = "255"; - var broadcast = String.join(".", splitIPAddr); - if (!setStatic(genSettings.ip, genSettings.netmask, genSettings.gateway, broadcast)) { - return false; - } - } else { - if (!setDHCP()) { - return false; - } - } - - return setHostname(genSettings.hostname); - } - - private static boolean setDHCP() { - if (!isManaged) { - return true; - } - return networking.setDHCP(); + NetworkInterface botInterface = goodInterfaces.get(0); + networking.setNetworkInterface(botInterface); + } else { + isManaged = false; + System.err.println("No valid network interfaces found! Staying unmanaged."); + } } - private static boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) { - if (!isManaged) { - return true; - } - return networking.setStatic(ipAddress, netmask, gateway, broadcast); + private static byte[] GetTeamNumberIPBytes(int teamNumber) { + return new byte[]{(byte) (teamNumber / 100), (byte) (teamNumber % 100)}; } - private static boolean setHostname(String hostname) { - if (!isManaged) { - return true; - } - return networking.setHostname(hostname); + + private static boolean setDHCP() { + if (!isManaged) { + return true; + } + return networking.setDHCP(); + } + + private static boolean setStatic(String ipAddress, String netmask, String gateway) { + if (!isManaged) { + return true; + } + return networking.setStatic(ipAddress, netmask, gateway); + } + + public static boolean setHostname(String hostname) { + if (!isManaged) { + return true; + } + return networking.setHostname(hostname); + } + + public static boolean setNetwork(boolean isStatic, String ip, String netmask, String gateway) { + if (isStatic) { + return setStatic(ip, netmask, gateway); + } else { + return setDHCP(); + } } } diff --git a/chameleon-server/src/main/java/com/chameleonvision/network/SysNetworking.java b/chameleon-server/src/main/java/com/chameleonvision/network/SysNetworking.java index 63a609984..7073809fb 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/network/SysNetworking.java +++ b/chameleon-server/src/main/java/com/chameleonvision/network/SysNetworking.java @@ -30,7 +30,7 @@ public abstract class SysNetworking { } public abstract boolean setDHCP(); public abstract boolean setHostname(String hostname); - public abstract boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast); + public abstract boolean setStatic(String ipAddress, String netmask, String gateway); public abstract List getNetworkInterfaces() throws SocketException; } diff --git a/chameleon-server/src/main/java/com/chameleonvision/network/WindowsNetworking.java b/chameleon-server/src/main/java/com/chameleonvision/network/WindowsNetworking.java index d03da14e2..c6fdae74f 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/network/WindowsNetworking.java +++ b/chameleon-server/src/main/java/com/chameleonvision/network/WindowsNetworking.java @@ -32,7 +32,7 @@ public class WindowsNetworking extends SysNetworking { } @Override - public boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) { + public boolean setStatic(String ipAddress, String netmask, String gateway) { return false; } diff --git a/chameleon-server/src/main/java/com/chameleonvision/web/RequestHandler.java b/chameleon-server/src/main/java/com/chameleonvision/web/RequestHandler.java index 55bc5e163..af82b6448 100644 --- a/chameleon-server/src/main/java/com/chameleonvision/web/RequestHandler.java +++ b/chameleon-server/src/main/java/com/chameleonvision/web/RequestHandler.java @@ -4,6 +4,7 @@ import com.chameleonvision.Exceptions.DuplicatedKeyException; import com.chameleonvision.Main; import com.chameleonvision.config.ConfigManager; import com.chameleonvision.network.NetworkIPMode; +import com.chameleonvision.network.NetworkManager; import com.chameleonvision.networktables.NetworkTablesManager; import com.chameleonvision.util.Helpers; import com.chameleonvision.util.Platform; @@ -53,8 +54,17 @@ public class RequestHandler { ConfigManager.settings.gateway = (String) map.get("gateway"); ConfigManager.settings.hostname = (String) map.get("hostname"); ConfigManager.saveGeneralSettings(); + // setting up network config after saving + boolean isStatic = ConfigManager.settings.connectionType.equals(NetworkIPMode.STATIC); + + if (NetworkManager.setHostname(ConfigManager.settings.hostname) && + NetworkManager.setNetwork(isStatic, ConfigManager.settings.ip, ConfigManager.settings.netmask, ConfigManager.settings.gateway)) { + ctx.status(200); + } else { + ctx.result("something went wrong while setting network configuration"); + ctx.status(501); + } SocketHandler.sendFullSettings(); - ctx.status(200); } catch (JsonProcessingException e) { ctx.status(500); }