Skip to content

Commit

Permalink
improve readability and rewrite local player check
Browse files Browse the repository at this point in the history
  • Loading branch information
Skidamek committed Nov 29, 2024
1 parent ec73c64 commit 1c6ba76
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 112 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private boolean canStart() {
}

if (serverConfig.updateIpsOnEveryStart || (serverConfig.hostIp == null || serverConfig.hostIp.isEmpty())) {
String publicIp = Ip.getPublic();
String publicIp = Ip.getPublicIp();
if (publicIp != null) {
serverConfig.hostIp = publicIp;
ConfigTools.save(serverConfigFile, serverConfig);
Expand All @@ -153,14 +153,15 @@ private boolean canStart() {

if (serverConfig.updateIpsOnEveryStart || (serverConfig.hostLocalIp == null || serverConfig.hostLocalIp.isEmpty())) {
try {
serverConfig.hostLocalIp = Ip.getLocal();
serverConfig.hostLocalIp = Ip.getLocalIp();
ConfigTools.save(serverConfigFile, serverConfig);
LOGGER.warn("Setting Host local IP to {}", serverConfig.hostLocalIp);
} catch (Exception e) {
e.printStackTrace();
}
}

LOGGER.info("Starting modpack host server on port {}", serverConfig.hostPort);
return true;
}
}
139 changes: 42 additions & 97 deletions core/src/main/java/pl/skidam/automodpack_core/utils/Ip.java
Original file line number Diff line number Diff line change
@@ -1,77 +1,53 @@
package pl.skidam.automodpack_core.utils;

import com.google.gson.JsonObject;

import java.net.*;
import java.util.Enumeration;
import java.util.Objects;

import static pl.skidam.automodpack_core.GlobalVariables.LOGGER;

public class Ip {
public static String getPublic() {
JsonObject JSON = null;
try {
JSON = Json.fromUrl("https://ip.seeip.org/json");
} catch (Exception e) {

public static String getPublicIp() {
String[] services = {
"https://ip.seeip.org/json",
"https://api.ipify.org?format=json"
};

for (String service : services) {
try {
JSON = Json.fromUrl("https://api.ipify.org?format=json");
} catch (Exception ex) {
LOGGER.error("AutoModpack couldn't get your public IP address, you need to type it manually into config");
return Objects.requireNonNull(Json.fromUrl(service)).get("ip").getAsString();
} catch (Exception ignored) {
// Try next service
}
}
if (JSON != null) {
return JSON.get("ip").getAsString();
}

LOGGER.error("AutoModpack couldn't get your public IP address, please configure it manually.");
return null;
}

public static String getLocal() {
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
// filters out 127.0.0.1 and inactive interfaces
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}

Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while(addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement();

if (addr.isLinkLocalAddress()) {
continue;
}

if (addr instanceof Inet4Address)
return addr.getHostAddress();
}
}
} catch (SocketException e) {
e.printStackTrace();
}
return null;
public static String getLocalIp() {
return getNetworkIp(Inet4Address.class);
}

public static String getLocalIpv6() {
return getNetworkIp(Inet6Address.class);
}

private static String getNetworkIp(Class<? extends InetAddress> ipClass) {
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
// filters out 127.0.0.1 and inactive interfaces
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
if (!networkInterface.isUp() || networkInterface.isLoopback()) {
continue;
}

Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress addr = addresses.nextElement();

if (addr instanceof Inet6Address) {
String hostAddress = addr.getHostAddress();
int idx = hostAddress.indexOf('%');
return idx < 0 ? hostAddress : hostAddress.substring(0, idx);
if (ipClass.isInstance(addr) && !addr.isLinkLocalAddress()) {
return addr.getHostAddress().split("%")[0];
}
}
}
Expand All @@ -82,78 +58,47 @@ public static String getLocalIpv6() {
}

public static boolean areIpsEqual(String ip1, String ip2) {
if (ip1 == null || ip2 == null) {
return false;
}

try {
InetAddress ia1 = InetAddress.getByName(ip1);
InetAddress ia2 = InetAddress.getByName(ip2);
return ia1.equals(ia2);
} catch (UnknownHostException ignored) { }

return InetAddress.getByName(ip1).equals(InetAddress.getByName(ip2));
} catch (UnknownHostException ignored) {
}
return false;
}

public static String refactorToTrueIp(String mcIp) {
if (mcIp == null) {
public static String normalizeIp(String ip) {
if (ip == null) {
return null;
}

String formattedPlayerIp = mcIp.trim();

if (formattedPlayerIp.charAt(0) == '/') {
formattedPlayerIp = formattedPlayerIp.substring(1);
ip = ip.trim();
if (ip.startsWith("/")) {
ip = ip.substring(1);
}

// remove port from ip
int portIdx = formattedPlayerIp.lastIndexOf(':');
if (portIdx > 0) {
formattedPlayerIp = formattedPlayerIp.substring(0, portIdx);
if (ip.contains(":")) { // Handle port or IPv6 scope
ip = ip.split(":", 2)[0];
}

if (formattedPlayerIp.startsWith("[") && formattedPlayerIp.endsWith("]")) {
formattedPlayerIp = formattedPlayerIp.substring(1, formattedPlayerIp.length() - 1);

int scopeIdx = formattedPlayerIp.indexOf('%');
if (scopeIdx > 0) {
formattedPlayerIp = formattedPlayerIp.substring(0, scopeIdx);
}
if (ip.startsWith("[") && ip.endsWith("]")) {
ip = ip.substring(1, ip.length() - 1);
}

return formattedPlayerIp;
return ip;
}

public static boolean isLocal(String ipToCheck, String configLocalIp) {
if (ipToCheck == null) {
public static boolean isLocal(String ip) {
if (ip == null) {
return true;
}

if (configLocalIp != null) {
if (areIpsEqual(ipToCheck, configLocalIp)) {
return true;
}

String reducedConfigLocalIp = configLocalIp;
if (configLocalIp.split("\\.").length == 4) {
reducedConfigLocalIp = configLocalIp.substring(0, configLocalIp.lastIndexOf("."));
}

if (ipToCheck.startsWith(reducedConfigLocalIp)) {
return true;
}
}
ip = normalizeIp(ip);
String localIp = getLocalIp();
String localIpv6 = getLocalIpv6();

boolean isLocal1 = ipToCheck.startsWith("192.168.") || ipToCheck.startsWith("0:0:0:0:") || ipToCheck.startsWith("::") || areIpsEqual(ipToCheck, "127.0.0.1");
if (isLocal1) {
if (ip.startsWith("192.168.") || ip.startsWith("127.") || ip.startsWith("::1") || ip.startsWith("0:0:0:0:")) {
return true;
}

boolean isLocal2 = areIpsEqual(ipToCheck, getLocal()) || areIpsEqual(ipToCheck, getLocalIpv6());
if (isLocal2) {
return true;
}

return false;
return areIpsEqual(ip, localIp) || areIpsEqual(ip, localIpv6);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,34 +94,38 @@ public static void handleHandshake(ClientConnection connection, String playerNam
String linkToSend;

// If the player is connecting locally or their IP matches a specified IP, use the local host IP and port
String formattedPlayerIp = Ip.refactorToTrueIp(playerIp);
String formattedPlayerIp = Ip.normalizeIp(playerIp);

// LOGGER.info("Player IP: {}", formattedPlayerIp);

if (Ip.isLocal(formattedPlayerIp, serverConfig.hostLocalIp)) { // local
if (Ip.isLocal(formattedPlayerIp)) { // local
linkToSend = serverConfig.hostLocalIp;
} else { // Otherwise, use the public host IP and port
linkToSend = serverConfig.hostIp;
}

// LOGGER.info("Sending {} modpack link: {}", playerName, linkToSend);

// We send empty string if hostIp/hostLocalIp is not specified in server config. Client will use ip by which it connected to the server in first place.
DataPacket dataPacket = new DataPacket("", serverConfig.modpackName, serverConfig.requireAutoModpackOnClient);

if (linkToSend != null && !linkToSend.isBlank()) {
if (!linkToSend.startsWith("http://") && !linkToSend.startsWith("https://")) {
linkToSend = "http://" + linkToSend;
}

if (!serverConfig.reverseProxy) {
// add port to link
if (serverConfig.hostPort != -1) {
linkToSend += ":" + serverConfig.hostPort;
} else if (serverConfig.hostModpackOnMinecraftPort) {
if (serverConfig.reverseProxy) {
// With reverse proxy we dont append port to the link, it should be already included in the link
// But we need to check if the port is set in the config, since that's where modpack is actually hosted
if (serverConfig.hostPort == -1) {
LOGGER.error("Reverse proxy is enabled but host port is not set in config! Please set it manually.");
}
} else { // Append server port
if (serverConfig.hostModpackOnMinecraftPort) {
linkToSend += ":" + minecraftServerPort;
} else {
linkToSend += ":" + serverConfig.hostPort;

if (serverConfig.hostPort == -1) {
LOGGER.error("Host port is not set in config! Please set it manually.");
}
}
} else if (serverConfig.hostPort == -1) {
LOGGER.error("Reverse proxy is enabled but host port is not set in config! Please set it manually.");
}

LOGGER.info("Sending {} modpack link: {}", playerName, linkToSend);
Expand Down

0 comments on commit 1c6ba76

Please sign in to comment.