Merge branch 'linux-networking' into dev

This commit is contained in:
ori agranat
2020-02-25 22:04:01 +02:00
8 changed files with 200 additions and 145 deletions

View File

@@ -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<String> 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<String> 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<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException {
List<java.net.NetworkInterface> netInterfaces;
try {
netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
} catch (SocketException e) {
return null;
}
@Override
public List<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException {
List<java.net.NetworkInterface> netInterfaces;
try {
netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
} catch (SocketException e) {
return null;
}
List<java.net.NetworkInterface> goodInterfaces = new ArrayList<>();
List<java.net.NetworkInterface> 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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -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<java.net.NetworkInterface> interfaces = new ArrayList<>();
List<NetworkInterface> goodInterfaces = new ArrayList<>();
List<java.net.NetworkInterface> interfaces = new ArrayList<>();
List<NetworkInterface> 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();
}
}
}

View File

@@ -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<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException;
}

View File

@@ -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;
}

View File

@@ -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);
}